Docker para desarrolladores
Guía completa de Docker para desarrollo y producción, con mejores prácticas empresariales y arquitecturas de microservicios.
¿Qué es Docker?
Docker es una plataforma que permite empaquetar aplicaciones y sus dependencias en contenedores ligeros y portables que pueden ejecutarse en cualquier sistema que tenga Docker instalado. Empresas como Netflix, Uber, Spotify y PayPal utilizan Docker para desplegar miles de microservicios diariamente.
Conceptos básicos
Imágenes
Una imagen es una plantilla de solo lectura que contiene todo lo necesario para ejecutar una aplicación.
# Descargar una imagen
docker pull node:18
# Listar imágenes
docker images
# Eliminar una imagen
docker rmi node:18
# Ver historial de capas de una imagen
docker history node:18
Contenedores
Un contenedor es una instancia en ejecución de una imagen.
# Ejecutar un contenedor
docker run -d -p 3000:3000 --name mi-app node:18
# Listar contenedores en ejecución
docker ps
# Listar todos los contenedores
docker ps -a
# Detener un contenedor
docker stop mi-app
# Eliminar un contenedor
docker rm mi-app
# Ver logs en tiempo real
docker logs -f mi-app
Dockerfile
Un Dockerfile define cómo construir una imagen personalizada.
# Imagen base
FROM node:18-alpine
# Directorio de trabajo
WORKDIR /app
# Copiar archivos de dependencias
COPY package*.json ./
# Instalar dependencias
RUN npm ci --only=production
# Copiar código fuente
COPY . .
# Exponer puerto
EXPOSE 3000
# Comando de inicio
CMD ["node", "server.js"]
Construir imagen
docker build -t mi-aplicacion:1.0 .
Docker Compose para Microservicios
Docker Compose permite definir y ejecutar aplicaciones multi-contenedor, ideal para arquitecturas de microservicios.
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
- db
- redis
volumes:
- ./src:/app/src
networks:
- app-network
restart: unless-stopped
db:
image: postgres:15-alpine
environment:
- POSTGRES_USER=usuario
- POSTGRES_PASSWORD=contraseña
- POSTGRES_DB=midb
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "5432:5432"
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U usuario"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
networks:
- app-network
volumes:
- redis-data:/data
volumes:
postgres-data:
redis-data:
networks:
app-network:
driver: bridge
Comandos de Docker Compose
# Iniciar servicios
docker-compose up -d
# Ver logs
docker-compose logs -f
# Ver logs de un servicio específico
docker-compose logs -f app
# Detener servicios
docker-compose down
# Detener y eliminar volúmenes
docker-compose down -v
# Reconstruir imágenes
docker-compose build
# Ejecutar comando en servicio
docker-compose exec app npm test
# Escalar servicios
docker-compose up -d --scale app=3
Mejores prácticas empresariales
1. Usar imágenes oficiales y específicas
# ✅ Bueno: versión específica
FROM node:18-alpine
# ❌ Malo: versión latest
FROM node:latest
2. Multi-stage builds para optimización
Los multi-stage builds reducen el tamaño de la imagen final hasta en un 90%, como lo implementa Google en sus contenedores.
# Stage 1: Build
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:18-alpine
WORKDIR /app
# Copiar solo lo necesario
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
# Usuario no-root para seguridad
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001 && \
chown -R nodejs:nodejs /app
USER nodejs
EXPOSE 3000
CMD ["node", "dist/server.js"]
3. Seguridad: Usuario no-root
Ejecutar contenedores como root es un riesgo de seguridad. Empresas como Amazon y Microsoft requieren contenedores no-root en producción.
# Crear usuario
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
# Cambiar permisos
RUN chown -R nodejs:nodejs /app
# Cambiar a usuario
USER nodejs
4. Minimizar capas y tamaño de imagen
# ✅ Bueno: combinar comandos
RUN apt-get update && \
apt-get install -y curl && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# ❌ Malo: múltiples RUN
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get clean
5. Usar .dockerignore
node_modules
npm-debug.log
.git
.env
.env.local
*.md
.DS_Store
coverage/
.vscode/
.idea/
dist/
build/
6. Gestión de secretos
Nunca incluyas secretos en la imagen. Usa variables de entorno o servicios de gestión de secretos.
# ❌ NUNCA hagas esto
ENV DATABASE_PASSWORD=mi-password-secreto
# ✅ Usa variables de entorno en runtime
# docker run -e DATABASE_PASSWORD=$DB_PASS mi-app
Docker en producción
Health checks
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node healthcheck.js
Límites de recursos
services:
app:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
Logging y monitoreo
# Configurar driver de logging
docker run --log-driver=json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
mi-app
# Ver estadísticas en tiempo real
docker stats
# Inspeccionar contenedor
docker inspect mi-app
Debugging
# Ejecutar shell en contenedor
docker exec -it mi-app /bin/sh
# Ver logs con timestamps
docker logs -f --timestamps mi-app
# Inspeccionar contenedor
docker inspect mi-app
# Ver uso de recursos
docker stats
# Ver procesos en contenedor
docker top mi-app
# Copiar archivos desde/hacia contenedor
docker cp mi-app:/app/logs ./logs
Arquitectura de microservicios con Docker
Empresas como Netflix ejecutan más de 700 microservicios en contenedores Docker. Aquí un ejemplo de arquitectura:
version: '3.8'
services:
# API Gateway
gateway:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- auth-service
- user-service
- order-service
# Servicio de autenticación
auth-service:
build: ./services/auth
environment:
- JWT_SECRET=${JWT_SECRET}
depends_on:
- redis
# Servicio de usuarios
user-service:
build: ./services/users
depends_on:
- postgres
# Servicio de pedidos
order-service:
build: ./services/orders
depends_on:
- postgres
- rabbitmq
# Message broker
rabbitmq:
image: rabbitmq:3-management-alpine
ports:
- "5672:5672"
- "15672:15672"
# Cache
redis:
image: redis:7-alpine
# Base de datos
postgres:
image: postgres:15-alpine
volumes:
- pg-data:/var/lib/postgresql/data
volumes:
pg-data:
Conclusión
Docker ha revolucionado el desarrollo y despliegue de aplicaciones modernas. Con estas mejores prácticas empresariales, puedes:
- Reducir el tamaño de imágenes hasta 90% con multi-stage builds
- Mejorar la seguridad ejecutando contenedores como usuarios no-root
- Escalar aplicaciones fácilmente con Docker Compose
- Implementar microservicios como lo hacen Netflix, Uber y Spotify
Docker no es solo una herramienta de desarrollo; es la base de la infraestructura moderna en la nube.
Gustavo Leyva
Desarrollador de Software