# ============================================================================= # Docker Compose para Producción - App Padel # Fase 7.4 - Go Live y Soporte # ============================================================================= # # Este archivo configura toda la infraestructura necesaria para producción: # - App Node.js (API) # - PostgreSQL (base de datos) # - Redis (cache/sessions - opcional) # - Nginx (reverse proxy y SSL) # # Uso: # docker-compose -f docker-compose.prod.yml up -d # # Escalar app: # docker-compose -f docker-compose.prod.yml up -d --scale app=3 # ============================================================================= version: '3.8' services: # --------------------------------------------------------------------------- # App Node.js - API REST # --------------------------------------------------------------------------- app: build: context: ./backend dockerfile: Dockerfile.prod container_name: padel-api restart: unless-stopped # Variables de entorno environment: - NODE_ENV=production - PORT=3000 - DATABASE_URL=postgresql://${DB_USER:-padeluser}:${DB_PASSWORD:-padelpass}@postgres:5432/${DB_NAME:-padeldb}?schema=public - JWT_SECRET=${JWT_SECRET} - JWT_EXPIRES_IN=${JWT_EXPIRES_IN:-7d} - JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET} - JWT_REFRESH_EXPIRES_IN=${JWT_REFRESH_EXPIRES_IN:-30d} - API_URL=${API_URL:-https://api.tudominio.com} - FRONTEND_URL=${FRONTEND_URL:-https://tudominio.com} # SMTP - SMTP_HOST=${SMTP_HOST} - SMTP_PORT=${SMTP_PORT:-587} - SMTP_USER=${SMTP_USER} - SMTP_PASS=${SMTP_PASS} - EMAIL_FROM=${EMAIL_FROM:-noreply@tudominio.com} # Rate Limiting - RATE_LIMIT_WINDOW_MS=${RATE_LIMIT_WINDOW_MS:-900000} - RATE_LIMIT_MAX_REQUESTS=${RATE_LIMIT_MAX_REQUESTS:-100} # MercadoPago - MERCADOPAGO_ACCESS_TOKEN=${MERCADOPAGO_ACCESS_TOKEN} - MERCADOPAGO_PUBLIC_KEY=${MERCADOPAGO_PUBLIC_KEY} - MERCADOPAGO_WEBHOOK_SECRET=${MERCADOPAGO_WEBHOOK_SECRET} # Redis (opcional) - REDIS_URL=${REDIS_URL:-redis://redis:6379} # Logging - LOG_LEVEL=${LOG_LEVEL:-info} # Dependencias depends_on: postgres: condition: service_healthy redis: condition: service_started # Volúmenes volumes: - app_logs:/app/logs - app_uploads:/app/uploads # Red networks: - padel_network # Recursos deploy: resources: limits: cpus: '1.0' memory: 1G reservations: cpus: '0.25' memory: 256M # Health check healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/api/v1/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s # --------------------------------------------------------------------------- # PostgreSQL - Base de datos principal # --------------------------------------------------------------------------- postgres: image: postgres:15-alpine container_name: padel-postgres restart: unless-stopped environment: - POSTGRES_USER=${DB_USER:-padeluser} - POSTGRES_PASSWORD=${DB_PASSWORD:-padelpass} - POSTGRES_DB=${DB_NAME:-padeldb} - PGDATA=/var/lib/postgresql/data/pgdata volumes: - postgres_data:/var/lib/postgresql/data # Backup automático diario - ./backups:/backups networks: - padel_network # Puerto expuesto solo internamente expose: - "5432" # Recursos deploy: resources: limits: cpus: '1.0' memory: 1G reservations: cpus: '0.25' memory: 256M # Health check healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-padeluser} -d ${DB_NAME:-padeldb}"] interval: 10s timeout: 5s retries: 5 start_period: 10s # Optimizaciones PostgreSQL para producción command: > postgres -c max_connections=100 -c shared_buffers=256MB -c effective_cache_size=768MB -c maintenance_work_mem=64MB -c checkpoint_completion_target=0.7 -c wal_buffers=16MB -c default_statistics_target=100 -c random_page_cost=1.1 -c effective_io_concurrency=200 -c work_mem=2621kB -c min_wal_size=1GB -c max_wal_size=4GB # --------------------------------------------------------------------------- # Redis - Cache y Sessions (Opcional) # --------------------------------------------------------------------------- redis: image: redis:7-alpine container_name: padel-redis restart: unless-stopped # Habilitar persistencia command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru volumes: - redis_data:/data networks: - padel_network expose: - "6379" # Recursos deploy: resources: limits: cpus: '0.5' memory: 256M reservations: cpus: '0.1' memory: 64M healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 3 # --------------------------------------------------------------------------- # Nginx - Reverse Proxy y SSL # --------------------------------------------------------------------------- nginx: image: nginx:alpine container_name: padel-nginx restart: unless-stopped ports: - "80:80" - "443:443" volumes: # Configuración de nginx - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/conf.d:/etc/nginx/conf.d:ro # Certificados SSL (Let's Encrypt o propios) - ./nginx/ssl:/etc/nginx/ssl:ro # Logs - nginx_logs:/var/log/nginx # Archivos estáticos (si se sirven desde nginx) - ./frontend/dist:/usr/share/nginx/html:ro networks: - padel_network depends_on: - app # Recursos deploy: resources: limits: cpus: '0.5' memory: 256M healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 # --------------------------------------------------------------------------- # Cron - Tareas programadas (backup, limpieza, etc.) # --------------------------------------------------------------------------- cron: build: context: ./backend dockerfile: Dockerfile.prod container_name: padel-cron restart: unless-stopped # Ejecutar script de backup en lugar de la app command: > sh -c " echo '0 2 * * * /app/scripts/backup.sh' | crontab - && echo '0 */6 * * * node /app/dist/scripts/cleanup-logs.js' | crontab - && crond -f " environment: - NODE_ENV=production - DATABASE_URL=postgresql://${DB_USER:-padeluser}:${DB_PASSWORD:-padelpass}@postgres:5432/${DB_NAME:-padeldb}?schema=public - BACKUP_S3_BUCKET=${BACKUP_S3_BUCKET} - BACKUP_S3_REGION=${BACKUP_S3_REGION} - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} volumes: - ./backups:/backups - app_logs:/app/logs networks: - padel_network depends_on: - postgres # --------------------------------------------------------------------------- # Volúmenes persistentes # --------------------------------------------------------------------------- volumes: postgres_data: driver: local redis_data: driver: local app_logs: driver: local app_uploads: driver: local nginx_logs: driver: local # --------------------------------------------------------------------------- # Redes # --------------------------------------------------------------------------- networks: padel_network: driver: bridge ipam: config: - subnet: 172.20.0.0/16