version: '3.8' services: app: build: context: . dockerfile: Dockerfile image: evoting-app:latest container_name: evoting-app-prod restart: always ports: - "80:3000" environment: - NODE_ENV=production - NEXT_PUBLIC_API_BASE_URL=${NEXT_PUBLIC_API_BASE_URL} - NEXT_PUBLIC_API_AUTH_HEADER=${NEXT_PUBLIC_API_AUTH_HEADER} - JWT_SECRET=${JWT_SECRET} - NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL} networks: - evoting-network depends_on: - db - redis healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/api/health', (r) => {if (r.statusCode !== 200) throw new Error()})"] interval: 30s timeout: 10s retries: 3 start_period: 40s # PostgreSQL Database db: image: postgres:15-alpine container_name: evoting-db-prod restart: always environment: - POSTGRES_USER=${DB_USER:-evoting} - POSTGRES_PASSWORD=${DB_PASSWORD:-secure_password_change_this} - POSTGRES_DB=${DB_NAME:-evoting_db} volumes: - postgres_data:/var/lib/postgresql/data - ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql networks: - evoting-network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-evoting}"] interval: 10s timeout: 5s retries: 5 # Redis for caching and sessions redis: image: redis:7-alpine container_name: evoting-redis-prod restart: always command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-redis_password_change_this} volumes: - redis_data:/data networks: - evoting-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 # Nginx as reverse proxy (optional but recommended) nginx: image: nginx:alpine container_name: evoting-nginx restart: always ports: - "443:443" - "80:80" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./nginx/ssl:/etc/nginx/ssl depends_on: - app networks: - evoting-network networks: evoting-network: driver: bridge volumes: postgres_data: driver: local redis_data: driver: local