version: '3.9' services: postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: timelapse POSTGRES_PASSWORD: timelapse_dev_password POSTGRES_DB: timelapse_dev volumes: - postgres_data:/var/lib/postgresql/data ports: - '5432:5432' healthcheck: test: ['CMD-SHELL', 'pg_isready -U timelapse'] interval: 5s timeout: 5s retries: 5 redis: image: redis:7-alpine restart: unless-stopped ports: - '6379:6379' volumes: - redis_data:/data healthcheck: test: ['CMD', 'redis-cli', 'ping'] interval: 5s timeout: 5s retries: 5 api-server: build: context: . dockerfile: apps/api-server/Dockerfile restart: unless-stopped environment: NODE_ENV: production PORT: '3001' DATABASE_URL: postgres://timelapse:timelapse_dev_password@postgres:5432/timelapse_dev REDIS_URL: redis://redis:6379 JWT_SECRET: ${JWT_SECRET:-change-this-secret-in-production} CORS_ORIGIN: ${CORS_ORIGIN:-http://localhost:3000} GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-} GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-} GOOGLE_CALLBACK_URL: ${GOOGLE_CALLBACK_URL:-http://localhost:3001/v1/auth/google/callback} UPLOAD_DIR: /uploads/captures SIM_INTERNAL_KEY: ${SIM_INTERNAL_KEY:-sim-internal-dev-key-123} ports: - '3001:3001' depends_on: postgres: condition: service_healthy redis: condition: service_healthy volumes: - ./apps/api-server/src:/app/src:ro - timelapse_uploads:/uploads/captures web-dashboard: build: context: . dockerfile: apps/web-dashboard/Dockerfile args: NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL} restart: unless-stopped environment: NODE_ENV: production NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL} ports: - '3000:3000' depends_on: - api-server worker: build: context: . dockerfile: apps/worker/Dockerfile restart: unless-stopped environment: NODE_ENV: production DATABASE_URL: postgres://timelapse:timelapse_dev_password@postgres:5432/timelapse_dev REDIS_URL: redis://redis:6379 depends_on: postgres: condition: service_healthy redis: condition: service_healthy simulator: build: context: . dockerfile: apps/simulator/Dockerfile restart: unless-stopped environment: SIM_SERVER_URL: http://api-server:3001 SIM_DEVICE_COUNT: '2' SIM_CAPTURE_INTERVAL: '30' SIM_INTERNAL_KEY: ${SIM_INTERNAL_KEY:-sim-internal-dev-key-123} depends_on: api-server: condition: service_started volumes: postgres_data: redis_data: timelapse_uploads: