# Zero-Downtime Deployment Configuration # Uses nginx as load balancer for seamless updates services: nginx: image: nginx:alpine container_name: portfolio-nginx restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./nginx-zero-downtime.conf:/etc/nginx/nginx.conf:ro networks: - portfolio_net depends_on: - portfolio-app-1 - portfolio-app-2 healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"] interval: 10s timeout: 5s retries: 3 portfolio-app-1: image: portfolio-app:latest container_name: portfolio-app-1 restart: unless-stopped environment: - NODE_ENV=${NODE_ENV:-production} - LOG_LEVEL=${LOG_LEVEL:-info} - DATABASE_URL=postgresql://portfolio_user:portfolio_pass@postgres:5432/portfolio_db?schema=public - REDIS_URL=redis://redis:6379 - NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL} - NEXT_PUBLIC_UMAMI_URL=${NEXT_PUBLIC_UMAMI_URL} - NEXT_PUBLIC_UMAMI_WEBSITE_ID=${NEXT_PUBLIC_UMAMI_WEBSITE_ID} - MY_EMAIL=${MY_EMAIL} - MY_INFO_EMAIL=${MY_INFO_EMAIL} - MY_PASSWORD=${MY_PASSWORD} - MY_INFO_PASSWORD=${MY_INFO_PASSWORD} - ADMIN_BASIC_AUTH=${ADMIN_BASIC_AUTH} volumes: - portfolio_data:/app/.next/cache networks: - portfolio_net depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"] interval: 10s timeout: 5s retries: 3 start_period: 30s portfolio-app-2: image: portfolio-app:latest container_name: portfolio-app-2 restart: unless-stopped environment: - NODE_ENV=${NODE_ENV:-production} - LOG_LEVEL=${LOG_LEVEL:-info} - DATABASE_URL=postgresql://portfolio_user:portfolio_pass@postgres:5432/portfolio_db?schema=public - REDIS_URL=redis://redis:6379 - NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL} - NEXT_PUBLIC_UMAMI_URL=${NEXT_PUBLIC_UMAMI_URL} - NEXT_PUBLIC_UMAMI_WEBSITE_ID=${NEXT_PUBLIC_UMAMI_WEBSITE_ID} - MY_EMAIL=${MY_EMAIL} - MY_INFO_EMAIL=${MY_INFO_EMAIL} - MY_PASSWORD=${MY_PASSWORD} - MY_INFO_PASSWORD=${MY_INFO_PASSWORD} - ADMIN_BASIC_AUTH=${ADMIN_BASIC_AUTH} volumes: - portfolio_data:/app/.next/cache networks: - portfolio_net depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"] interval: 10s timeout: 5s retries: 3 start_period: 30s postgres: image: postgres:16-alpine container_name: portfolio-postgres restart: unless-stopped environment: - POSTGRES_DB=portfolio_db - POSTGRES_USER=portfolio_user - POSTGRES_PASSWORD=portfolio_pass volumes: - postgres_data:/var/lib/postgresql/data networks: - portfolio_net healthcheck: test: ["CMD-SHELL", "pg_isready -U portfolio_user -d portfolio_db"] interval: 10s timeout: 5s retries: 5 start_period: 30s redis: image: redis:7-alpine container_name: portfolio-redis restart: unless-stopped volumes: - redis_data:/data networks: - portfolio_net healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 30s volumes: portfolio_data: driver: local postgres_data: driver: local redis_data: driver: local networks: portfolio_net: driver: bridge