commit f84cfed6d2bf966a101e3f74557a526ffa437ef6 Author: Me Date: Sat Mar 14 11:25:27 2020 +0100 Initial commit diff --git a/DockerFile b/DockerFile new file mode 100644 index 0000000..4bfe904 --- /dev/null +++ b/DockerFile @@ -0,0 +1,9 @@ +FROM python:3-alpine + +ADD dst.py / + +RUN pip install docker + +VOLUME [ "/data" ] + +CMD [ "python", "./dst.py" ] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..eb0fac2 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# Docker Status + +Simple status page using Docker sdk and healthcheck. + +## Options + +Environment variable | Description | Default +--- | --- | --- +DOCKER_* | Docker client options | [Doc](https://docker-py.readthedocs.io/en/stable/client.html#docker.client.from_env) +DST_PATH | Json file output | `/data/status.json` +DST_INTERVAL | Update interval is seconds | `30` +DST_FILTER_LABEL | Filter visible containers with label | `False` +DST_NAME_LABEL | Override container name with label | `False` +DST_URL_LABEL | Provide url with label | `False` + +## TODO + +[x] Json periodic static +[ ] Static Front +[ ] Groups +[ ] Events +[ ] Gotify \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3180ba8 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,25 @@ +version: '2' + +volumes: + data: + driver: local + +services: + dst: + build: . + restart: always + container_name: dst + environment: + - DST_FILTER_LABEL=fr.wadza.dst.visible=true + - DST_NAME_LABEL=fr.wadza.dst.name + - DST_URL_LABEL=fr.wadza.dst.url + labels: + - fr.wadza.dst.visible=true + - fr.wadza.dst.name=Status + - fr.wadza.dst.url=https://status.wadza.fr + volumes: + - data:/data + - /var/run/docker.sock:/var/run/docker.sock + mem_limit: 512m + mem_reservation: 128m + memswap_limit: 0 \ No newline at end of file diff --git a/dst.py b/dst.py new file mode 100644 index 0000000..7276ff6 --- /dev/null +++ b/dst.py @@ -0,0 +1,48 @@ +import docker +import json +import time +import os + +path = os.environ.get("DST_PATH", "/data/status.json") +interval = int(os.environ.get("DST_INTERVAL", "30")) +filter_label = os.environ.get("DST_FILTER_LABEL", False) +filters = {} +if filter_label: + filters["label"] = filter_label +name_label = os.environ.get("DST_NAME_LABEL", False) +url_label = os.environ.get("DST_URL_LABEL", False) + +client = docker.from_env() + +def formatContainer(container): + state = container.attrs.get("State", {}) + health = state.get("Health", {}) + return { + "name": container.labels.get(name_label, container.name), + "url": container.labels.get(url_label), + "status": container.status, + "start": state.get("StartedAt"), + "stop": state.get("FinishedAt"), + "health": { + "status": health.get("Status", "none"), + "fails": health.get("FailingStreak", 0) + } + } + +def loop(): + while True: + try: + report = list( + map(formatContainer, + client.containers.list(all=True, filters=filters))) + with open(path, 'w') as outfile: + json.dump(report, outfile) + except docker.errors.NotFound: + print('Container bad move. Restarting.') + time.sleep(interval) + +try: + loop() +except KeyboardInterrupt: + print('\n\nKeyboard exception received. Exiting.') + exit() \ No newline at end of file