services: speedtest: build: ./measurement container_name: speedtest restart: unless-stopped volumes: - sqlite-data:/data environment: - DB_PATH=/data/speedtest.db - SPEEDTEST_ENABLED=${SPEEDTEST_ENABLED:-true} ping: build: ./measurement container_name: ping restart: unless-stopped network_mode: host volumes: - sqlite-data:/data environment: - DB_PATH=/data/speedtest.db - PING_INTERVAL=${PING_INTERVAL:-5} command: python3 /app/run_ping.py control: build: ./measurement container_name: control restart: unless-stopped ports: - "${CONTROL_PORT:-80}:80" volumes: - sqlite-data:/data environment: - DB_PATH=/data/speedtest.db - SPEEDTEST_ENABLED=${SPEEDTEST_ENABLED:-true} - GRAFANA_PORT=${GRAFANA_PORT} command: python3 /app/control.py grafana: image: grafana/grafana:latest container_name: grafana restart: unless-stopped ports: - "${GRAFANA_PORT}:3000" environment: - GF_SECURITY_ADMIN_USER=${GRAFANA_ADMIN_USER} - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD} - GF_INSTALL_PLUGINS=frser-sqlite-datasource - GF_AUTH_ANONYMOUS_ENABLED=true - GF_AUTH_ANONYMOUS_ORG_NAME=Main Org. - GF_AUTH_ANONYMOUS_ORG_ROLE=Viewer - GF_AUTH_ANONYMOUS_HIDE_VERSION=true # SQL-computed labels (patterns, raw table, SLA day grouping) use SQLite's # 'localtime', which resolves to this container's timezone. - TZ=${TZ:-Etc/UTC} volumes: # :ro because any Grafana viewer (incl. anonymous) can send arbitrary SQL # to the datasource API; the mount and mode=ro keep that harmless. - sqlite-data:/data:ro - ./grafana/provisioning:/etc/grafana/provisioning volumes: sqlite-data: external: true name: speed-logger_sqlite-data