version: '3.8' services: nginx: image: nginx:1.25-alpine container_name: invest-copilot-nginx ports: - "443:443" - "80:80" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/ssl:/etc/nginx/ssl:ro depends_on: backend: condition: service_healthy frontend: condition: service_healthy healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:80/health >/dev/null 2>&1 || exit 1"] interval: 30s timeout: 10s retries: 3 restart: unless-stopped backend: build: context: ../.. dockerfile: src/backend/Dockerfile.prod container_name: invest-copilot-backend environment: DATABASE_URL: postgresql+asyncpg://prod:${POSTGRES_PASSWORD}@postgres:5432/invest_copilot REDIS_URL: redis://redis:6379/0 MINIO_ENDPOINT: minio:9000 MINIO_ACCESS_KEY: prod MINIO_SECRET_KEY: ${MINIO_SECRET_KEY} JWT_SECRET: ${JWT_SECRET} CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost} LOG_LEVEL: info depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"] interval: 30s timeout: 10s retries: 3 restart: unless-stopped deploy: resources: limits: cpus: '2' memory: 2G frontend: build: context: ../.. dockerfile: src/frontend/Dockerfile.prod container_name: invest-copilot-frontend environment: NEXT_PUBLIC_API_URL: http://backend:8000/api/v1 NEXT_PUBLIC_WS_URL: ws://backend:8000 depends_on: backend: condition: service_healthy healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"] interval: 30s timeout: 10s retries: 3 restart: unless-stopped deploy: resources: limits: cpus: '1' memory: 512M postgres: image: timescale/timescaledb:latest-pg16 container_name: invest-copilot-postgres-prod environment: POSTGRES_DB: invest_copilot POSTGRES_USER: prod POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} ports: - "127.0.0.1:5432:5432" volumes: - pgdata:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/01-init.sql healthcheck: test: ["CMD-SHELL", "pg_isready -U prod -d invest_copilot"] interval: 10s timeout: 5s retries: 10 restart: unless-stopped command: > postgres -c max_connections=200 -c shared_buffers=256MB -c effective_cache_size=768MB -c work_mem=4MB -c maintenance_work_mem=64MB -c wal_level=replica -c max_wal_senders=3 redis: image: redis:7-alpine container_name: invest-copilot-redis-prod command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru volumes: - redisdata:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped minio: image: minio/minio container_name: invest-copilot-minio-prod command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: prod MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY} volumes: - miniodata:/data healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped volumes: pgdata: redisdata: miniodata: