Files
math2-platform/docker/docker-compose.yml
Renato bc43c9e772
Some checks failed
Test Suite / test-backend (push) Has been cancelled
Test Suite / test-frontend (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / coverage-check (push) Has been cancelled
🎓 Initial commit: Math2 Platform - Plataforma de Álgebra Lineal PRO
 Características:
- 45 ejercicios universitarios (Basic → Advanced)
- Renderizado LaTeX profesional
- IA generativa (Z.ai/DashScope)
- Docker 9 servicios
- Tests 123/123 pasando
- Seguridad enterprise (JWT, XSS, Rate limiting)

🐳 Infraestructura:
- Next.js 14 + Node.js 20
- PostgreSQL 15 + Redis 7
- Docker Compose completo
- Nginx + SSL ready

📚 Documentación:
- 5 informes técnicos completos
- README profesional
- Scripts de deployment automatizados

Estado: Producción lista 
2026-03-31 11:27:11 -03:00

572 lines
15 KiB
YAML

# ==================================================
# DOCKER COMPOSE - VERSIÓN DETALLADA
# Plataforma de Estudio de Matemáticas
# ==================================================
# Este archivo contiene configuraciones detalladas para
# desarrollo, testing y producción.
#
# Uso:
# docker-compose -f docker/docker-compose.yml up -d
# ==================================================
version: '3.9'
services:
# ==================================================
# POSTGRESQL - Base de Datos Principal
# ==================================================
postgres:
image: postgres:15.4-alpine
container_name: math-postgres
restart: unless-stopped
environment:
POSTGRES_USER: mathuser
POSTGRES_PASSWORD: ${DB_PASSWORD:-math_secure_password_2024}
POSTGRES_DB: mathdb
POSTGRES_INITDB_ARGS: "-E UTF8 --locale=C"
volumes:
# Persistencia de datos
- postgres_data:/var/lib/postgresql/data
# Scripts de inicialización
- ./init-scripts:/docker-entrypoint-initdb.d:ro
ports:
- "${POSTGRES_PORT:-5432}:5432"
command: [
"postgres",
"-c", "max_connections=200",
"-c", "shared_buffers=256MB",
"-c", "effective_cache_size=1GB",
"-c", "maintenance_work_mem=64MB",
"-c", "checkpoint_completion_target=0.9",
"-c", "wal_buffers=16MB",
"-c", "default_statistics_target=100",
"-c", "random_page_cost=1.1",
"-c", "effective_io_concurrency=200",
"-c", "work_mem=1310kB",
"-c", "min_wal_size=1GB",
"-c", "max_wal_size=4GB",
"-c", "log_statement=all",
"-c", "log_duration=on"
]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U mathuser -d mathdb"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
- math-network
labels:
- "com.math-platform.description=PostgreSQL Database"
- "com.math-platform.priority=1"
# ==================================================
# REDIS - Cache & Message Queue
# ==================================================
redis:
image: redis:7.2.3-alpine
container_name: math-redis
restart: unless-stopped
command: >
redis-server
--appendonly yes
--appendfsync everysec
--requirepass ${REDIS_PASSWORD:-redis_secure_password_2024}
--maxmemory 256mb
--maxmemory-policy allkeys-lru
--tcp-backlog 511
--timeout 0
--tcp-keepalive 300
volumes:
- redis_data:/data
ports:
- "${REDIS_PORT:-6379}:6379"
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 10s
timeout: 3s
retries: 5
start_period: 5s
networks:
- math-network
labels:
- "com.math-platform.description=Redis Cache & Queue"
- "com.math-platform.priority=2"
# ==================================================
# BACKEND API - Node.js + Express + TypeScript
# ==================================================
backend:
build:
context: ..
dockerfile: docker/Dockerfile.backend
target: runner
args:
NODE_VERSION: "20"
container_name: math-backend
restart: unless-stopped
environment:
# Node.js
NODE_ENV: ${NODE_ENV:-production}
PORT: 3001
# Database
DATABASE_URL: postgresql://mathuser:${DB_PASSWORD:-math_secure_password_2024}@postgres:5432/mathdb
DB_PASSWORD: ${DB_PASSWORD:-math_secure_password_2024}
# Redis
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-redis_secure_password_2024}
# AI (MiniMax-M2.5 via Aliyun DashScope)
AI_API_BASE_URL: ${AI_API_BASE_URL:-https://coding-intl.dashscope.aliyuncs.com/v1}
AI_API_KEY: ${AI_API_KEY:-your-dashscope-api-key-here}
AI_MODEL: ${AI_MODEL:-MiniMax-M2.5}
AI_MAX_TOKENS: ${AI_MAX_TOKENS:-2000}
AI_TEMPERATURE: ${AI_TEMPERATURE:-0.7}
# Telegram
TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN}
TELEGRAM_ADMIN_CHAT_ID: ${TELEGRAM_ADMIN_CHAT_ID}
# JWT
JWT_SECRET: ${JWT_SECRET:-jwt_secret_key_change_in_production}
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d}
JWT_REFRESH_EXPIRES_IN: ${JWT_REFRESH_EXPIRES_IN:-30d}
# CORS
CORS_ORIGIN: ${CORS_ORIGIN:-http://localhost:3000}
# Rate Limiting
RATE_LIMIT_AUTH: ${RATE_LIMIT_AUTH:-5}
RATE_LIMIT_API: ${RATE_LIMIT_API:-10}
RATE_LIMIT_WINDOW_MS: ${RATE_LIMIT_WINDOW_MS:-60000}
volumes:
# Code mounting (for development without rebuild)
- ../backend:/app
- /app/node_modules
# PDFs directory (read-only)
- ../pdfs:/app/pdfs:ro
# Logs
- ./logs/backend:/app/logs
ports:
- "${BACKEND_PORT:-3001}:3001"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3001/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- math-network
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
labels:
- "com.math-platform.description=Backend API"
- "com.math-platform.priority=3"
# ==================================================
# FRONTEND - Next.js 14 App Router
# ==================================================
frontend:
build:
context: ..
dockerfile: docker/Dockerfile.frontend
target: runner
args:
NODE_VERSION: "20"
container_name: math-frontend
restart: unless-stopped
environment:
NODE_ENV: ${NODE_ENV:-production}
PORT: 3000
# API URL
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://backend:3001}
NEXT_PUBLIC_APP_NAME: ${NEXT_PUBLIC_APP_NAME:-Plataforma de Álgebra Lineal}
# Next.js
NEXT_TELEMETRY_DISABLED: "1"
volumes:
# Code mounting (for development)
- ../frontend:/app
- /app/node_modules
- /app/.next
# Logs
- ./logs/frontend:/app/logs
ports:
- "${FRONTEND_PORT:-3000}:3000"
depends_on:
backend:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- math-network
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
labels:
- "com.math-platform.description=Frontend (Next.js)"
- "com.math-platform.priority=4"
# ==================================================
# PDF WORKER - Procesamiento de PDFs
# ==================================================
pdf-worker:
build:
context: ..
dockerfile: docker/Dockerfile.worker
target: pdf-worker
container_name: math-pdf-worker
restart: unless-stopped
environment:
NODE_ENV: ${NODE_ENV:-production}
WORKER_TYPE: pdf
# Database
DATABASE_URL: postgresql://mathuser:${DB_PASSWORD:-math_secure_password_2024}@postgres:5432/mathdb
# Redis
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-redis_secure_password_2024}
# PDF Processing
PDF_PROCESSING_BATCH_SIZE: ${PDF_PROCESSING_BATCH_SIZE:-5}
PDF_PROCESSING_TIMEOUT: ${PDF_PROCESSING_TIMEOUT:-300000}
PDF_STORAGE_PATH: /app/pdfs
PDF_PROCESSED_PATH: /app/pdfs/processed
# Worker
WORKER_RETRY_ATTEMPTS: ${WORKER_RETRY_ATTEMPTS:-3}
WORKER_RETRY_DELAY: ${WORKER_RETRY_DELAY:-5000}
volumes:
- ../backend:/app
- /app/node_modules
- ../pdfs:/app/pdfs:ro
- ../pdfs/processed:/app/pdfs/processed
- ./logs/pdf-worker:/app/logs
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "node", "-e", "console.log('healthy')"]
interval: 60s
timeout: 10s
retries: 3
start_period: 30s
networks:
- math-network
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
reservations:
cpus: '0.1'
memory: 64M
replicas: ${PDF_WORKER_REPLICAS:-1}
labels:
- "com.math-platform.description=PDF Processing Worker"
- "com.math-platform.priority=5"
# ==================================================
# EXERCISE WORKER - Generación de Ejercicios con IA
# ==================================================
exercise-worker:
build:
context: ..
dockerfile: docker/Dockerfile.worker
target: exercise-worker
container_name: math-exercise-worker
restart: unless-stopped
environment:
NODE_ENV: ${NODE_ENV:-production}
WORKER_TYPE: exercise
# Database
DATABASE_URL: postgresql://mathuser:${DB_PASSWORD:-math_secure_password_2024}@postgres:5432/mathdb
# Redis
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-redis_secure_password_2024}
# AI
AI_API_BASE_URL: ${AI_API_BASE_URL:-https://coding-intl.dashscope.aliyuncs.com/v1}
AI_API_KEY: ${AI_API_KEY}
AI_MODEL: ${AI_MODEL:-MiniMax-M2.5}
AI_MAX_TOKENS: ${AI_MAX_TOKENS:-2000}
AI_TEMPERATURE: ${AI_TEMPERATURE:-0.7}
# Worker
WORKER_RETRY_ATTEMPTS: ${WORKER_RETRY_ATTEMPTS:-3}
WORKER_RETRY_DELAY: ${WORKER_RETRY_DELAY:-5000}
volumes:
- ../backend:/app
- /app/node_modules
- ./logs/exercise-worker:/app/logs
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "node", "-e", "console.log('healthy')"]
interval: 60s
timeout: 10s
retries: 3
start_period: 30s
networks:
- math-network
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
reservations:
cpus: '0.1'
memory: 64M
replicas: ${EXERCISE_WORKER_REPLICAS:-2}
labels:
- "com.math-platform.description=Exercise Generation Worker (AI)"
- "com.math-platform.priority=6"
# ==================================================
# NOTIFICATION WORKER - Envío de Notificaciones Telegram
# ==================================================
notification-worker:
build:
context: ..
dockerfile: docker/Dockerfile.worker
target: notification-worker
container_name: math-notification-worker
restart: unless-stopped
environment:
NODE_ENV: ${NODE_ENV:-production}
WORKER_TYPE: notification
# Database
DATABASE_URL: postgresql://mathuser:${DB_PASSWORD:-math_secure_password_2024}@postgres:5432/mathdb
# Redis
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-redis_secure_password_2024}
# Telegram
TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN}
TELEGRAM_ADMIN_CHAT_ID: ${TELEGRAM_ADMIN_CHAT_ID}
# Worker
WORKER_RETRY_ATTEMPTS: ${WORKER_RETRY_ATTEMPTS:-3}
WORKER_RETRY_DELAY: ${WORKER_RETRY_DELAY:-5000}
volumes:
- ../backend:/app
- /app/node_modules
- ./logs/notification-worker:/app/logs
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "node", "-e", "console.log('healthy')"]
interval: 60s
timeout: 10s
retries: 3
start_period: 30s
networks:
- math-network
deploy:
resources:
limits:
cpus: '0.25'
memory: 128M
reservations:
cpus: '0.05'
memory: 32M
replicas: ${NOTIFICATION_WORKER_REPLICAS:-1}
labels:
- "com.math-platform.description=Notification Worker (Telegram)"
- "com.math-platform.priority=7"
# ==================================================
# NGINX - Reverse Proxy + Load Balancer
# ==================================================
nginx:
image: nginx:1.25-alpine
container_name: math-nginx
restart: unless-stopped
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./logs/nginx:/var/log/nginx
# SSL certificates (uncomment for production)
# - ./ssl:/etc/nginx/ssl:ro
ports:
- "${NGINX_HTTP_PORT:-80}:80"
- "${NGINX_HTTPS_PORT:-443}:443"
depends_on:
- frontend
- backend
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
networks:
- math-network
deploy:
resources:
limits:
cpus: '0.5'
memory: 128M
reservations:
cpus: '0.1'
memory: 32M
labels:
- "com.math-platform.description=Nginx Reverse Proxy"
- "com.math-platform.priority=8"
# ==================================================
# VOLUMES - Persistencia de Datos
# ==================================================
volumes:
postgres_data:
driver: local
driver_opts:
type: none
o: bind
device: ./data/postgres
redis_data:
driver: local
driver_opts:
type: none
o: bind
device: ./data/redis
# ==================================================
# NETWORKS - Comunicación entre Servicios
# ==================================================
networks:
math-network:
driver: bridge
driver_opts:
com.docker.network.bridge.name: math_br
ipam:
driver: default
config:
- subnet: 172.20.0.0/16
# ==================================================
# CONFIGURACIÓN ADICIONAL
# ==================================================
#
# Perfiles de ejecución:
#
# Desarrollo:
# docker-compose -f docker/docker-compose.yml --profile dev up
#
# Producción:
# docker-compose -f docker/docker-compose.yml --profile prod up -d
#
# Escalado de workers:
# docker-compose -f docker/docker-compose.yml up -d --scale exercise-worker=3
#
# Logs en tiempo real:
# docker-compose -f docker/docker-compose.yml logs -f backend
#
# Reconstrucción completa:
# docker-compose -f docker/docker-compose.yml build --no-cache
#
# Backup de base de datos:
# docker-compose -f docker/docker-compose.yml exec postgres \
# pg_dump -U mathuser mathdb > backup_$(date +%Y%m%d).sql
#
# Restauración de base de datos:
# docker-compose -f docker/docker-compose.yml exec -T postgres \
# psql -U mathuser mathdb < backup_20240323.sql