# Production override — use with: # docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build # # For SSL add docker-compose.ssl.yml as well: # docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.ssl.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, not Vite) # - No source-code volume mounts (uses baked-in built code) # - Memory limits and health checks on backend # - Restart policies for reliability services: nginx: ports: - "80:80" - "443:443" volumes: - ./nginx/production.conf:/etc/nginx/conf.d/default.conf:ro - certbot_www:/var/www/certbot:ro - certbot_conf:/etc/letsencrypt: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 certbot: image: certbot/certbot:latest volumes: - certbot_www:/var/www/certbot - certbot_conf:/etc/letsencrypt networks: - hoanet entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --quiet; sleep 12h & wait $${!}; done'" volumes: certbot_www: certbot_conf: