# CI-only data-plane overlay. # # The live host runs the long-lived data-plane services (timescaledb, mosquitto, # redis, mosquitto-reloader) as a separate meshcore-infra project on the shared # bridge network. GitHub-hosted runners have no such project, so the compose # validation and empty-volume smoke test need the definitions here. # # Never use this file for a real deployment; it exists purely so `ci.yml` can # merge a self-contained stack with `docker compose -f docker-compose.yml # -f docker-compose.ci.yml`. services: timescaledb: image: timescale/timescaledb@sha256:22e8a5ae7aef121d1537afe946dd7cc5deeeb63ab36ce19849d671bd3b663509 logging: &json-log-limits options: max-size: "10m" max-file: "3" mem_limit: "4g" memswap_limit: "4g" stop_grace_period: 2m # The image currently tunes timescaledb.max_background_workers to 16. # Leave headroom for the Timescale launcher/schedulers, logical replication, # and a policy worker so scheduled jobs do not fail their first launch. command: - postgres - -c - max_connections=300 - -c - max_worker_processes=${POSTGRES_MAX_WORKER_PROCESSES:-24} - -c - max_parallel_workers_per_gather=0 environment: POSTGRES_DB: ${POSTGRES_DB:-meshcore} POSTGRES_USER: ${POSTGRES_USER:-meshcore} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD required} volumes: - ./backend/src/db/schema/base.sql:/docker-entrypoint-initdb.d/001_schema.sql:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-meshcore} -d ${POSTGRES_DB:-meshcore}"] interval: 30s timeout: 10s retries: 10 start_period: 30s mosquitto: image: eclipse-mosquitto@sha256:9cfdd46ad59f3e3e5f592f6baf57ab23e1ad00605509d0f5c1e9b179c5314d87 logging: *json-log-limits mem_limit: "128m" memswap_limit: "128m" healthcheck: test: ["CMD-SHELL", "pgrep mosquitto >/dev/null && nc -z 127.0.0.1 9001"] interval: 30s timeout: 10s retries: 5 start_period: 10s volumes: - ./mosquitto:/mosquitto/config - mosquitto_data:/mosquitto/data - mosquitto_log:/mosquitto/log mosquitto-reloader: image: ${MOSQUITTO_RELOADER_IMAGE:-meshcore-analytics-mosquitto-reloader:local} build: context: . dockerfile: Dockerfile.mosquitto-reloader args: SOURCE_REVISION: ${SOURCE_REVISION:-local} restart: "no" logging: *json-log-limits mem_limit: "64m" memswap_limit: "64m" pid: "service:mosquitto" # Match the broker UID inside the shared PID namespace so SIGHUP can be # delivered without granting CAP_KILL or root. user: "1883:1883" cap_drop: - ALL security_opt: - no-new-privileges:true read_only: true environment: OWNER_ACL_RELOAD_TOKEN: ${JWT_SECRET:?JWT_SECRET required} MOSQUITTO_LOG_PATH: /mosquitto/log/mosquitto.log volumes: - mosquitto_log:/mosquitto/log depends_on: mosquitto: condition: service_healthy healthcheck: test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/healthz', timeout=2).read()"] interval: 30s timeout: 5s retries: 5 redis: image: redis@sha256:8b81dd37ff027bec4e516d41acfbe9fe2460070dc6d4a4570a2ac5b9d59df065 logging: *json-log-limits mem_limit: "512m" memswap_limit: "512m" command: - redis-server - --requirepass - ${REDIS_PASSWORD:?REDIS_PASSWORD required} - --maxmemory - 448mb - --maxmemory-policy - noeviction - --appendonly - "yes" - --appendfsync - everysec environment: REDIS_PASSWORD: ${REDIS_PASSWORD} healthcheck: test: ["CMD-SHELL", "redis-cli -a $REDIS_PASSWORD --no-auth-warning ping"] interval: 30s timeout: 10s retries: 5