services: postgres: image: postgres:16-alpine container_name: vidreview-db environment: POSTGRES_USER: vidreview POSTGRES_PASSWORD: vidreview123 POSTGRES_DB: vidreview ports: - '5432:5432' volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U vidreview'] interval: 5s timeout: 5s retries: 5 # ── Init (runs once on fresh deploy) ─────────────────────────────────────── init: build: context: . dockerfile: Dockerfile.api container_name: vidreview-init entrypoint: ['bash', '/scripts/init-admin.sh'] environment: DB_HOST: vidreview-db DB_NAME: vidreview DB_USER: vidreview DB_PASS: vidreview123 API_CONTAINER: vidreview-api OUTPUT_DIR: /seed-output ADMIN_EMAIL: admin@vidreview.local ADMIN_NAME: Admin volumes: - /var/run/docker.sock:/var/run/docker.sock:rw - /usr/bin/docker:/usr/bin/docker:rw - ./scripts:/scripts - seed_output:/seed-output depends_on: postgres: condition: service_healthy api: condition: service_healthy restart: 'no' api: build: context: . dockerfile: Dockerfile.api container_name: vidreview-api environment: DATABASE_URL: postgresql://vidreview:vidreview123@postgres:5432/vidreview JWT_SECRET: ${JWT_SECRET:-change-me-in-production} JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d} API_PORT: 3001 NODE_ENV: production UPLOAD_DIR: /app/uploads MAX_FILE_SIZE_MB: 500 ALLOWED_ORIGINS: 'https://vid.k9tech.space,http://vid.k9tech.space,http://10.147.17.128,http://192.168.1.31' FRONTEND_URL: https://vid.k9tech.space RESEND_API_KEY: ${RESEND_API_KEY:-} ports: - '3001:3001' depends_on: postgres: condition: service_healthy volumes: - uploads:/app/uploads healthcheck: test: ['CMD-SHELL', 'wget -qO- http://localhost:3001/health || exit 1'] interval: 10s timeout: 5s retries: 5 # ── Transcode Worker ────────────────────────────────────────────────────── worker: build: context: . dockerfile: Dockerfile.api container_name: vidreview-worker command: node src/worker/index.js environment: DATABASE_URL: postgresql://vidreview:vidreview123@postgres:5432/vidreview NODE_ENV: production UPLOAD_DIR: /app/uploads POLL_INTERVAL_MS: 2000 depends_on: postgres: condition: service_healthy volumes: - uploads:/app/uploads restart: unless-stopped # ── Caddy Reverse Proxy ─────────────────────────────────────────────────── # Receives HTTP traffic forwarded by Synology reverse proxy. # Routes /api/* → api container, everything else → frontend. caddy: image: caddy:2-alpine container_name: vidreview-caddy ports: - '80:80' - '443:443' volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config depends_on: - frontend - api frontend: build: context: . dockerfile: Dockerfile.frontend container_name: vidreview-frontend environment: NEXT_PUBLIC_API_URL: https://vid.k9tech.space/api NODE_ENV: production expose: - '3000' depends_on: api: condition: service_healthy volumes: postgres_data: uploads: seed_output: caddy_data: caddy_config: