version: "2.4" services: redis: image: ${REDIS_BASE_IMAGE:-redis:7-alpine} container_name: truckwash-redis restart: unless-stopped command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD:?set REDIS_PASSWORD}"] environment: REDIS_PASSWORD: "${REDIS_PASSWORD:?set REDIS_PASSWORD}" volumes: - ./runtime/redis:/data healthcheck: test: ["CMD-SHELL", 'redis-cli -a "$$REDIS_PASSWORD" ping | grep -q PONG'] interval: 30s timeout: 5s retries: 5 mariadb: image: ${MARIADB_BASE_IMAGE:-mariadb:11} container_name: truckwash-mariadb restart: unless-stopped environment: MARIADB_DATABASE: ${MARIADB_DATABASE:-truckwash_edge} MARIADB_USER: ${MARIADB_USER:-truckwash_edge} MARIADB_PASSWORD: "${MARIADB_PASSWORD:?set MARIADB_PASSWORD}" MARIADB_ROOT_PASSWORD: "${MARIADB_ROOT_PASSWORD:?set MARIADB_ROOT_PASSWORD}" volumes: - ./runtime/mariadb:/var/lib/mysql minio: image: ${MINIO_BASE_IMAGE:-minio/minio:latest} container_name: truckwash-minio restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: "${MINIO_ROOT_USER:?set MINIO_ROOT_USER}" MINIO_ROOT_PASSWORD: "${MINIO_ROOT_PASSWORD:?set MINIO_ROOT_PASSWORD}" volumes: - ./runtime/minio:/data lan-worker: build: context: . dockerfile: Dockerfile.lan-worker args: BASE_IMAGE: ${LAN_WORKER_BASE_IMAGE:-php:8.2-cli-bookworm} container_name: truckwash-lan-worker restart: unless-stopped ports: - "127.0.0.1:8090:8090" depends_on: redis: condition: service_healthy mariadb: condition: service_started minio: condition: service_started volumes: - ./config.json:/config/config.json:ro - ./runtime:/opt/truckwash-edge-agent/runtime healthcheck: test: [ "CMD", "php", "-r", "$$json=@file_get_contents('http://127.0.0.1:8090/health'); if ($$json===false) exit(1); $$data=json_decode($$json,true); exit((($$data['status'] ?? '') === 'healthy') ? 0 : 1);", ] interval: 30s timeout: 5s retries: 3 edge-agent: build: context: . dockerfile: Dockerfile.edge-agent args: BASE_IMAGE: ${EDGE_AGENT_BASE_IMAGE:-php:8.2-cli-bookworm} container_name: truckwash-edge-agent restart: unless-stopped depends_on: redis: condition: service_healthy mariadb: condition: service_started minio: condition: service_started lan-worker: condition: service_healthy volumes: - ./config.json:/config/config.json - ./runtime:/opt/truckwash-edge-agent/runtime healthcheck: test: [ "CMD-SHELL", "php -r '$$path=\"/opt/truckwash-edge-agent/runtime/control-plane-status.json\"; if (!is_file($$path)) { exit(1); } $$data=json_decode((string)file_get_contents($$path), true); if (!is_array($$data)) { exit(1); } $$loopAt=strtotime((string)($$data[\"last_loop_at\"] ?? \"\")); $$syncAt=strtotime((string)($$data[\"last_successful_sync_at\"] ?? $$data[\"started_at\"] ?? \"\")); if ($$loopAt === false || $$syncAt === false) { exit(1); } $$now=time(); exit((($$now - $$loopAt) <= 30 && ($$now - $$syncAt) <= 90) ? 0 : 1);'", ] interval: 30s timeout: 5s retries: 3 auto-updater: build: context: . dockerfile: Dockerfile.auto-updater args: BASE_IMAGE: ${AUTO_UPDATER_BASE_IMAGE:-php:8.2-cli-bookworm} container_name: truckwash-auto-updater restart: unless-stopped depends_on: edge-agent: condition: service_started environment: AUTO_UPDATER_INTERVAL_SECONDS: 30 volumes: - .:/opt/truckwash-edge-agent - /var/run/docker.sock:/var/run/docker.sock healthcheck: test: [ "CMD-SHELL", "php -r '$$path=\"/opt/truckwash-edge-agent/runtime/auto-updater-heartbeat.json\"; if (!is_file($$path)) { exit(1); } exit((time() - filemtime($$path)) <= 90 ? 0 : 1);'", ] interval: 30s timeout: 5s retries: 3