services: db: image: postgres:16-alpine environment: POSTGRES_USER: cayce POSTGRES_PASSWORD: localdev-only-not-a-secret POSTGRES_DB: cayce_ops ports: - "127.0.0.1:5432:5432" # loopback only — Docker bypasses host firewalls volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U cayce -d cayce_ops"] interval: 5s timeout: 3s retries: 10 # One container per daemon; all run the same image and differ only in command. # Cron-style cadence via `sleep` loop; on a VPS prefer the systemd timers in # deploy/systemd/ (they are the primary deployment path). scanner: build: . command: sh -c "while true; do cayceops scanner run; sleep 3600; done" env_file: .env environment: CAYCE_OPS_DATABASE_URL: postgresql+psycopg://cayce:localdev-only-not-a-secret@db:5432/cayce_ops depends_on: db: condition: service_healthy executor: build: . command: sh -c "while true; do cayceops executor run; sleep 600; done" env_file: .env environment: CAYCE_OPS_DATABASE_URL: postgresql+psycopg://cayce:localdev-only-not-a-secret@db:5432/cayce_ops depends_on: db: condition: service_healthy maild: build: . command: sh -c "while true; do cayceops maild poll && cayceops maild send-approved; sleep 300; done" env_file: .env environment: CAYCE_OPS_DATABASE_URL: postgresql+psycopg://cayce:localdev-only-not-a-secret@db:5432/cayce_ops depends_on: db: condition: service_healthy publisher: build: . command: sh -c "while true; do cayceops publisher publish-due; sleep 300; done" env_file: .env environment: CAYCE_OPS_DATABASE_URL: postgresql+psycopg://cayce:localdev-only-not-a-secret@db:5432/cayce_ops depends_on: db: condition: service_healthy monitor: build: . command: sh -c "while true; do cayceops monitor build; sleep 60; done" environment: CAYCE_OPS_DATABASE_URL: postgresql+psycopg://cayce:localdev-only-not-a-secret@db:5432/cayce_ops CAYCE_OPS_MONITOR_OUTPUT: /srv/status.html volumes: - ./status:/srv depends_on: db: condition: service_healthy volumes: pgdata: