version: '3.8' services: # PostgreSQL Database postgres: image: postgres:15-alpine container_name: tournament-postgres-prod environment: POSTGRES_DB: tournament POSTGRES_USER: tournament_user POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change_me_in_production} volumes: - postgres_data:/var/lib/postgresql/data - ../prisma/migrations:/docker-entrypoint-initdb.d ports: - "127.0.0.1:5432:5432" # Only accessible from localhost healthcheck: test: ["CMD-SHELL", "pg_isready -U tournament_user -d tournament"] interval: 10s timeout: 5s retries: 5 networks: - tournament-network restart: unless-stopped # Tournament Application tournament-app: build: context: .. dockerfile: docker/Dockerfile container_name: tournament-app-prod environment: - DATABASE_URL=postgresql://tournament_user:${POSTGRES_PASSWORD:-change_me_in_production}@postgres:5432/tournament - PORT=4000 - JWT_SECRET=${JWT_SECRET:-change_me_in_production} - ADMIN_USERNAME=${ADMIN_USERNAME:-admin} - ADMIN_PASSWORD=${ADMIN_PASSWORD:-change_me_in_production} - ADMIN_EMAIL=${ADMIN_EMAIL:-admin@tournament.com} - NODE_ENV=production ports: - "127.0.0.1:4000:4000" # Only accessible from localhost depends_on: postgres: condition: service_healthy volumes: - ../prisma:/app/prisma networks: - tournament-network restart: unless-stopped deploy: resources: limits: memory: 512M cpus: '0.5' reservations: memory: 256M cpus: '0.25' # Nginx Reverse Proxy nginx: image: nginx:alpine container_name: tournament-nginx-prod ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - ./ssl:/etc/nginx/ssl:ro - nginx_logs:/var/log/nginx depends_on: - tournament-app networks: - tournament-network restart: unless-stopped deploy: resources: limits: memory: 128M cpus: '0.25' reservations: memory: 64M cpus: '0.1' volumes: postgres_data: driver: local nginx_logs: driver: local networks: tournament-network: driver: bridge ipam: config: - subnet: 172.20.0.0/16