| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- services:
- postgres:
- image: postgres:16-alpine
- container_name: vidreview-db
- environment:
- POSTGRES_USER: ${POSTGRES_USER:-vidreview}
- POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Required}
- POSTGRES_DB: ${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 ─────────────────────────────────────
- # Creates admin account, locks registration, saves credentials to seed_output.
- # Skips silently if DB already has an admin (safe to re-run on updates).
- init:
- build:
- context: .
- dockerfile: Dockerfile.api
- container_name: vidreview-init
- entrypoint: ['bash', '/scripts/init-admin.sh']
- environment:
- DB_HOST: postgres
- DB_NAME: ${POSTGRES_DB:-vidreview}
- DB_USER: ${POSTGRES_USER:-vidreview}
- DB_PASS: ${POSTGRES_PASSWORD:?Required}
- API_CONTAINER: vidreview-api
- OUTPUT_DIR: /seed-output
- ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@vidreview.local}
- ADMIN_NAME: ${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 ─────────────────────────────────────────────────────────────────
- api:
- build:
- context: .
- dockerfile: Dockerfile.api
- container_name: vidreview-api
- environment:
- DATABASE_URL: ${DATABASE_URL:?Required}
- JWT_SECRET: ${JWT_SECRET:?Required}
- JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d}
- API_PORT: 3001
- NODE_ENV: ${NODE_ENV:-production}
- UPLOAD_DIR: /app/uploads
- MAX_FILE_SIZE_MB: ${MAX_FILE_SIZE_MB:-500}
- ALLOWED_ORIGINS: ${ALLOWED_ORIGINS}
- FRONTEND_URL: ${FRONTEND_URL}
- 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: ${DATABASE_URL:?Required}
- NODE_ENV: ${NODE_ENV:-production}
- UPLOAD_DIR: /app/uploads
- POLL_INTERVAL_MS: ${POLL_INTERVAL_MS:-2000}
- depends_on:
- postgres:
- condition: service_healthy
- volumes:
- - uploads:/app/uploads
- restart: unless-stopped
- # ── Caddy Reverse Proxy ──────────────────────────────────────────────────
- caddy:
- image: caddy:2-alpine
- container_name: vidreview-caddy
- ports:
- - '${CADDY_HTTP_PORT:-80}:80'
- - '${CADDY_HTTPS_PORT:-443}:443'
- volumes:
- - ./Caddyfile:/etc/caddy/Caddyfile:ro
- - caddy_data:/data
- - caddy_config:/config
- depends_on:
- - frontend
- - api
- # ── Frontend ────────────────────────────────────────────────────────────
- frontend:
- build:
- context: .
- dockerfile: Dockerfile.frontend
- container_name: vidreview-frontend
- environment:
- NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
- NODE_ENV: ${NODE_ENV:-production}
- expose:
- - '3000'
- depends_on:
- api:
- condition: service_healthy
- volumes:
- postgres_data:
- uploads:
- seed_output:
- caddy_data:
- caddy_config:
|