Configuración de Docker
Tabla de Contenidos
- Propósito
- ¿Para quién es esto?
- Arquitectura de Dockerfile
- Configuración de Docker Compose
- Construcción de Imágenes Docker
- Ejecución de Servicios con Docker
- Referencia de Comandos Docker
- Verificación y Health Checks
- Solución de Problemas
Propósito
Esta guía explica la configuración de Docker para la plataforma Algesta, cubriendo Dockerfiles para microservicios individuales y configuraciones de Docker Compose para desarrollo local y pruebas. Proporciona análisis detallado de builds multi-etapa, gestión de dependencias y orquestación de contenedores.
Siguiendo esta guía, entenderás:
- Estructura y optimización de Dockerfile multi-etapa
- Cómo construir imágenes Docker listas para producción
- Configuración de Docker Compose para desarrollo full-stack
- Health checks y gestión de dependencias
- Redes de contenedores y gestión de volúmenes
¿Para quién es esto?
Esta guía es para desarrolladores ejecutando servicios en contenedores localmente, ingenieros DevOps preparando imágenes para despliegue y administradores de sistemas gestionando entornos contenerizados. Asume familiaridad con Docker, Docker Compose y conceptos de contenerización.
Arquitectura de Dockerfile
Todos los microservicios de Algesta usan Dockerfiles multi-etapa para optimizar el tamaño de imagen y eficiencia de build. El patrón sigue dos etapas: Builder (compilación) y Final (runtime).
Dockerfile del Microservicio Orders
Ubicación: algesta-ms-orders-nestjs/Dockerfile
# ============================# Builder Stage# ============================FROM node:20-slim AS builder
WORKDIR /appCOPY package*.json ./RUN npm ci# Si husky falla no detiene el procesoRUN npm install -g husky && npx husky install || echo "husky skipped"COPY . .RUN npm run build
# ============================# Final Stage# ============================FROM node:20-slim
WORKDIR /appCOPY package*.json ./# Instala Puppeteer con ChromiumRUN apt-get update && \ apt-get install -y wget ca-certificates fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libdrm2 libgbm1 libnspr4 libnss3 libx11-xcb1 libxcomposite1 libxdamage1 libxrandr2 xdg-utils# Instala todo lo necesario, incluyendo bcrypt compiladoRUN npm install --force --only=production bcryptCOPY --from=builder /app/dist ./distCOPY --from=builder /app/src/shared/templates ./dist/src/shared/templatesENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=falseEXPOSE 3000
CMD ["node", "dist/main"]Desglose del Dockerfile
Etapa Builder
Propósito: Compilar TypeScript a JavaScript, ejecutar pasos de build
Pasos Clave:
- Imagen Base:
node:20-slim- Imagen mínima de Node.js 20 - Directorio de Trabajo:
/app - Copiar Archivos de Paquetes:
package*.jsonpara instalación de dependencias - Instalar Dependencias:
npm cipara instalaciones limpias y reproducibles - Configuración de Husky: Instalar git hooks (se salta si falla, no es crítico para build)
- Copiar Código Fuente: Copiar todos los archivos fuente
- Build:
npm run buildcompila TypeScript adist/
¿Por Qué Etapa Builder?
- Separa dependencias de build del runtime
- Reduce tamaño final de imagen (sin devDependencies)
- Cachea capa de npm install para rebuilds más rápidos
Etapa Final
Propósito: Crear imagen de producción ligera con solo dependencias de runtime
Pasos Clave:
- Imagen Base:
node:20-slimfresco - Dependencias del Sistema: Instalar dependencias de Puppeteer/Chromium:
wget,ca-certificates: Capacidades de descarga- Librerías de fuentes: Renderizado de texto en PDFs
- Librerías GTK/X11: Soporte de navegador sin cabeza
- Dependencias de Producción:
npm install --force --only=production bcrypt--only=production: Excluir devDependencies--force: Reconstruir módulos nativos (bcrypt) para arquitectura correcta
- Copiar Artefactos:
- Código compilado del builder:
/app/dist - Plantillas de email:
/app/src/shared/templates(requerido en runtime)
- Código compilado del builder:
- Entorno:
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=falseasegura que Chromium esté disponible - Exponer Puerto:
3000(sobreescrito por env PORT en producción) - Comando:
node dist/main- Iniciar aplicación compilada
¿Por Qué Compilación Nativa?
bcryptusa bindings nativos compilados para la arquitectura del host- Etapa builder se ejecuta en máquina de build (ej., macOS, Linux x86)
- Etapa final puede ejecutarse en arquitectura diferente (ej., Cloud Run en Linux ARM)
- Reconstruir en etapa final asegura compatibilidad
Dockerfile para Otros Microservicios
Microservicios Notifications y Provider usan Dockerfiles similares con diferencias menores:
- Notifications: Puede omitir dependencias de Puppeteer si no genera PDFs
- Provider: Incluye SDKs de Azure Storage, configuración similar de Puppeteer
API Gateway tiene Dockerfile más simple (sin Puppeteer, sin bcrypt):
FROM node:20-slim AS builderWORKDIR /appCOPY package*.json ./RUN npm ciCOPY . .RUN npm run build
FROM node:20-slimWORKDIR /appCOPY package*.json ./RUN npm install --only=productionCOPY --from=builder /app/dist ./distEXPOSE 3000CMD ["node", "dist/main"]Configuración de Docker Compose
Docker Compose orquesta múltiples contenedores para desarrollo local, habilitando pruebas full-stack sin gestión manual de servicios.
Docker Compose de Servicio Individual
Ejemplo: algesta-ms-orders-nestjs/docker-compose.yml
version: "3.8"
services: postgres: image: postgres:15-alpine container_name: auth-ms-postgres environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: auth_ms ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data networks: - auth_network healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5
auth-ms: build: context: . dockerfile: Dockerfile container_name: auth-ms depends_on: postgres: condition: service_healthy environment: - NODE_ENV=development - DB_HOST=postgres - DB_PORT=5432 - DB_USERNAME=postgres - DB_PASSWORD=postgres - DB_DATABASE=auth_ms ports: - "3000:3000" networks: - auth_network
volumes: postgres_data:
networks: auth_network: name: auth_network driver: bridgeNota: El ejemplo anterior es del repositorio de Orders MS pero referencia Postgres (probablemente desactualizado de una plantilla). Algesta usa MongoDB, no Postgres.
Docker Compose Full-Stack
Configuración Recomendada: Crear docker-compose.yml en directorio raíz de Algesta para todos los servicios.
version: "3.8"
services: # ============================ # Infrastructure Services # ============================ mongodb: image: mongo:7 container_name: algesta-mongodb ports: - "27017:27017" volumes: - algesta-mongo-data:/data/db networks: - algesta-network healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped
redis: image: redis:7-alpine container_name: algesta-redis ports: - "6379:6379" volumes: - algesta-redis-data:/data networks: - algesta-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped
kafka: image: confluentinc/cp-kafka:7.5.0 container_name: algesta-kafka depends_on: - zookeeper ports: - "9092:9092" environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 networks: - algesta-network restart: unless-stopped
zookeeper: image: confluentinc/cp-zookeeper:7.5.0 container_name: algesta-zookeeper ports: - "2181:2181" environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_TICK_TIME: 2000 networks: - algesta-network restart: unless-stopped
# ============================ # Microservices # ============================ orders-ms: build: context: ./algesta-ms-orders-nestjs dockerfile: Dockerfile container_name: algesta-orders-ms depends_on: mongodb: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started environment: - NODE_ENV=development - PORT=3001 - MONGODB_URI=mongodb://mongodb:27017/orders_ms - REDIS_HOST=redis - REDIS_PORT=6379 - KAFKA_BROKERS=kafka:9092 - JWT_SECRET=dev-secret-minimum-32-characters-long-for-local ports: - "3001:3001" networks: - algesta-network volumes: - ./algesta-ms-orders-nestjs:/app - /app/node_modules restart: unless-stopped
notifications-ms: build: context: ./algesta-ms-notifications-nestjs dockerfile: Dockerfile container_name: algesta-notifications-ms depends_on: mongodb: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started environment: - NODE_ENV=development - PORT=3002 - MONGODB_URI=mongodb://mongodb:27017/notifications_ms - REDIS_HOST=redis - REDIS_PORT=6379 - KAFKA_BROKERS=kafka:9092 ports: - "3002:3002" networks: - algesta-network restart: unless-stopped
provider-ms: build: context: ./algesta-ms-provider-nestjs dockerfile: Dockerfile container_name: algesta-provider-ms depends_on: mongodb: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started environment: - NODE_ENV=development - PORT=3003 - MONGODB_URI=mongodb://mongodb:27017/providers_ms - REDIS_HOST=redis - REDIS_PORT=6379 - KAFKA_BROKERS=kafka:9092 - JWT_SECRET=dev-secret-minimum-32-characters-long-for-local ports: - "3003:3003" networks: - algesta-network restart: unless-stopped
api-gateway: build: context: ./algesta-api-gateway-nestjs dockerfile: Dockerfile container_name: algesta-api-gateway depends_on: - orders-ms - notifications-ms - provider-ms - redis environment: - NODE_ENV=development - PORT=3000 - MS_ORDERS_URL=http://orders-ms:3001 - MS_NOTIFICATIONS_URL=http://notifications-ms:3002 - MS_PROVIDER_URL=http://provider-ms:3003 - REDIS_HOST=redis - REDIS_PORT=6379 - JWT_SECRET=dev-secret-minimum-32-characters-long-for-local - RATE_LIMIT_MAX=100 - RATE_LIMIT_WINDOW_MS=60000 ports: - "3000:3000" networks: - algesta-network restart: unless-stopped
volumes: algesta-mongo-data: algesta-redis-data:
networks: algesta-network: driver: bridgeFuncionalidades de Docker Compose
Health Checks
Propósito: Asegurar que las dependencias estén listas antes de iniciar servicios dependientes
Health Check de MongoDB:
healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 10s timeout: 5s retries: 5Explicación:
- Comando de Prueba: Hace ping a MongoDB para verificar que responde
- Intervalo: Verificar cada 10 segundos
- Timeout: Esperar máximo 5 segundos para respuesta
- Reintentos: Reintentar 5 veces antes de marcar como no saludable
Beneficios:
- Previene condiciones de carrera (ej., servicio intentando conectar a MongoDB antes de que esté listo)
depends_on.condition: service_healthyespera a que health check pase
Gestión de Dependencias
Orden de Inicio:
depends_on: mongodb: condition: service_healthy # Wait for health check redis: condition: service_healthy kafka: condition: service_started # Just wait for container start (no health check)Orden de Operaciones:
- Iniciar infraestructura: MongoDB, Redis, Zookeeper, Kafka
- Esperar a que health checks pasen
- Iniciar microservicios (Orders, Notifications, Provider)
- Iniciar API Gateway (depende de todos los microservicios)
Volúmenes
Volúmenes Nombrados:
volumes: algesta-mongo-data: # Persists MongoDB data algesta-redis-data: # Persists Redis snapshotsBind Mounts (Desarrollo):
volumes: - ./algesta-ms-orders-nestjs:/app # Sincronizar cambios de código - /app/node_modules # Preservar node_modules del contenedorBeneficios:
- Volúmenes Nombrados: Persistir datos a través de reinicios de contenedor
- Bind Mounts: Habilitar hot-reload durante desarrollo
- Volumen Anónimo
/app/node_modules: Previene que node_modules del host sobreescriba los del contenedor
Redes
Red Bridge:
networks: algesta-network: driver: bridgeBeneficios:
- Todos los servicios en la misma red pueden comunicarse vía nombres de servicio
mongodb://mongodb:27017resuelve al contenedor de MongoDB- Aislado de la red del host (a menos que los puertos estén expuestos)
Construir Imágenes Docker
Construir Servicio Individual
cd algesta-ms-orders-nestjsdocker build -t algesta-orders-ms:latest .Construir con Tag Personalizado:
docker build -t algesta-orders-ms:v1.0.0 .Construir para Plataforma Específica:
docker build --platform linux/amd64 -t algesta-orders-ms:latest .Verificación:
docker images | grep algesta-orders-ms# Esperado: algesta-orders-ms latest <image-id> X minutes ago XMBConstruir Todos los Servicios (Docker Compose)
cd ~/Documents/3A/Algesta # Root directory with docker-compose.ymldocker-compose buildBuild with No Cache (force rebuild):
docker-compose build --no-cacheBuild Specific Service:
docker-compose build orders-msVerification:
docker-compose images# Lists all images built by docker-composeRunning Services with Docker
Run Individual Service
docker run -d \ --name algesta-orders-ms \ -p 3001:3001 \ -e NODE_ENV=development \ -e MONGODB_URI=mongodb://host.docker.internal:27017/orders_ms \ -e REDIS_HOST=host.docker.internal \ -e JWT_SECRET=dev-secret \ algesta-orders-ms:latestFlags:
-d: Detached mode (run in background)--name: Container name-p 3001:3001: Port mapping (host:container)-e: Environment variableshost.docker.internal: Host machine IP from container perspective (macOS/Windows)
Run All Services (Docker Compose)
cd ~/Documents/3A/Algestadocker-compose up -dCommands:
# Start all services in foreground (see logs)docker-compose up
# Start in background (detached)docker-compose up -d
# Start specific servicedocker-compose up -d orders-ms
# Rebuild and startdocker-compose up -d --build
# Stop all servicesdocker-compose down
# Stop and remove volumes (data loss!)docker-compose down -vVerification:
docker-compose ps# Shows status of all services
docker-compose logs -f# Follow logs from all services
docker-compose logs -f orders-ms# Follow logs from specific serviceDocker Commands Reference
Container Management
# List running containersdocker ps
# List all containers (including stopped)docker ps -a
# Start containerdocker start algesta-orders-ms
# Stop containerdocker stop algesta-orders-ms
# Restart containerdocker restart algesta-orders-ms
# Remove containerdocker rm algesta-orders-ms
# Remove all stopped containersdocker container pruneImage Management
# List imagesdocker images
# Remove imagedocker rmi algesta-orders-ms:latest
# Remove unused imagesdocker image prune
# Remove all unused images (including dangling)docker image prune -aLogs and Debugging
# View logsdocker logs algesta-orders-ms
# Follow logs (real-time)docker logs -f algesta-orders-ms
# Last 100 linesdocker logs --tail 100 algesta-orders-ms
# Logs since timestampdocker logs --since 2025-11-20T10:00:00 algesta-orders-ms
# Execute command in running containerdocker exec -it algesta-orders-ms bash
# Inspect container detailsdocker inspect algesta-orders-ms
# View container resource usagedocker stats algesta-orders-msNetworking
# List networksdocker network ls
# Inspect networkdocker network inspect algesta-network
# Create networkdocker network create algesta-network
# Connect container to networkdocker network connect algesta-network algesta-orders-msVolumes
# List volumesdocker volume ls
# Inspect volumedocker volume inspect algesta-mongo-data
# Remove volumedocker volume rm algesta-mongo-data
# Remove unused volumesdocker volume pruneVerification and Health Checks
1. Check Container Estado
docker-compose ps# Expected: All services "Up" with healthy statusSample Output:
NAME STATUS PORTSalgesta-api-gateway Up 2 minutes 0.0.0.0:3000->3000/tcpalgesta-mongodb Up 2 minutes (healthy) 0.0.0.0:27017->27017/tcpalgesta-orders-ms Up 2 minutes 0.0.0.0:3001->3001/tcpalgesta-redis Up 2 minutes (healthy) 0.0.0.0:6379->6379/tcp2. Health Check Endpoints
# API Gatewaycurl http://localhost:3000/health | jq .
# Orders MScurl http://localhost:3001/health | jq .
# Notifications MScurl http://localhost:3002/health | jq .
# Provider MScurl http://localhost:3003/health | jq .Expected Response:
{ "status": "ok", "timestamp": "2025-11-20T12:00:00.000Z", "uptime": 120}3. Test Service Communication
# From API Gateway, test routing to Orders MScurl -X POST http://localhost:3000/orders \ -H "Content-Type: application/json" \ -d '{"service":"Test","address":"Test Address","city":"Bogotá"}'4. Check Base de datos Connectivity
# Execute MongoDB command in containerdocker exec algesta-mongodb mongosh --eval "show dbs"
# Expected: orders_ms, notifications_ms, providers_ms5. Monitor Container Resources
docker stats# Shows CPU, memory, network I/O for all containersTroubleshooting
Issue: Container fails to start with “Cannot connect to Base de datos”
Diagnosis:
docker-compose logs orders-ms# Look for connection errorsSolutions:
- Verify MongoDB is healthy:
Ventana de terminal docker-compose ps mongodb# Should show "Up (healthy)" - Check network connectivity:
Ventana de terminal docker exec algesta-orders-ms ping mongodb - Verify environment variables:
Ventana de terminal docker exec algesta-orders-ms printenv | grep MONGODB_URI - Ensure
depends_onwith health check is configured
Issue: Puppeteer fails with “Failed to launch Chrome”
Diagnosis:
docker exec algesta-orders-ms which chromium# Should return path to chromiumSolutions:
- Verify system dependencies installed in Dockerfile
- Check Puppeteer environment variables:
Ventana de terminal docker exec algesta-orders-ms printenv | grep PUPPETEER - Test Chromium manually:
Ventana de terminal docker exec algesta-orders-ms chromium --version - Ensure image rebuilt after Dockerfile changes:
Ventana de terminal docker-compose build --no-cache orders-ms
Issue: bcrypt fails with “Version mismatch”
Cause: bcrypt compiled for wrong Arquitectura (e.g., macOS arm64 vs Linux x86)
Solution: Rebuild bcrypt in Dockerfile final stage:
RUN npm install --force --only=production bcryptVerification:
docker exec algesta-orders-ms node -e "require('bcrypt').hash('test', 10, console.log)"# Should output hash without errorsIssue: Hot reload not working with bind mounts
Solution:
Add polling to NestJS in main.ts:
if (module.hot) { module.hot.accept(); module.hot.dispose(() => app.close());}Or use nodemon with polling:
{ "watch": ["src"], "ext": "ts", "legacy-watch": true}Issue: Port already in use
Diagnosis:
lsof -i :3001# Shows process using port 3001Solution:
# Kill processkill -9 <PID>
# Or change Docker port mappingdocker-compose down# Edit docker-compose.yml to use different port# e.g., - "3011:3001"docker-compose up -dRelated Guías:
- Local Development Setup: Running services without Docker
- Environment Configuration: Environment variables reference
- Despliegue Guía: Building images for production
- Troubleshooting: Docker-specific issues
For Support:
- Review Dockerfile comments in each Microservicio
- Check Docker Compose logs:
docker-compose logs -f - Validate images with
docker inspect <image-name>