# Production override — use with: # docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build # # What this changes from the base (dev) config: # - Backend: production Dockerfile (compiled JS, no watch, no devDeps) # - Frontend: production Dockerfile (static build served by nginx on port 3001) # - No source-code volume mounts (uses baked-in built code) # - Memory limits and health checks on backend # - Tuned PostgreSQL for production workloads # - Restart policies for reliability # # SSL/TLS is handled at the host level (e.g., host nginx + certbot). # The Docker nginx container listens on port 80 only. services: nginx: volumes: - ./nginx/production.conf:/etc/nginx/conf.d/default.conf:ro restart: unless-stopped backend: build: context: ./backend dockerfile: Dockerfile # production Dockerfile (compiled JS) volumes: [] # override: no source mounts in prod environment: - DATABASE_URL=${DATABASE_URL} - REDIS_URL=${REDIS_URL} - JWT_SECRET=${JWT_SECRET} - NODE_ENV=production - AI_API_URL=${AI_API_URL} - AI_API_KEY=${AI_API_KEY} - AI_MODEL=${AI_MODEL} - AI_DEBUG=${AI_DEBUG:-false} deploy: resources: limits: memory: 1024M reservations: memory: 256M healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:3000/api || exit 1"] interval: 15s timeout: 5s retries: 3 start_period: 30s restart: unless-stopped frontend: build: context: ./frontend dockerfile: Dockerfile # production Dockerfile (static nginx) volumes: [] # override: no source mounts in prod environment: - NODE_ENV=production restart: unless-stopped postgres: # Tune PostgreSQL for production workloads command: > postgres -c max_connections=200 -c shared_buffers=256MB -c effective_cache_size=512MB -c work_mem=4MB -c maintenance_work_mem=64MB -c checkpoint_completion_target=0.9 -c wal_buffers=16MB -c random_page_cost=1.1 deploy: resources: limits: memory: 1024M reservations: memory: 512M restart: unless-stopped redis: restart: unless-stopped