Contenedorización con Docker y Kubernetes

La contenedorización ha revolucionado la forma en que construimos, enviamos y ejecutamos software. Al empaquetar aplicaciones con sus dependencias en unidades portátiles y livianas, los contenedores resuelven el problema de "funciona en mi máquina" y permiten una implementación consistente en entornos de desarrollo, pruebas y producción.
Introducción
La contenedorización ha revolucionado la forma en que construimos, enviamos y ejecutamos software. Al empaquetar aplicaciones con sus dependencias en unidades portátiles y livianas, los contenedores resuelven el problema de "funciona en mi máquina" y permiten una implementación consistente en entornos de desarrollo, pruebas y producción.
Docker hizo que los contenedores fueran accesibles. Kubernetes los hizo manejables a escala. Juntos, forman la columna vertebral de la implementación moderna de aplicaciones nativas de la nube.
¿Qué son los contenedores?
Contenedores versus máquinas virtuales
┌───────────────────────┐ ┌───────────────────────┐
│ Virtual Machine │ │ Container │
├───────────────────────┤ ├───────────────────────┤
│ ┌─────────────────┐ │ │ ┌─────────────────┐ │
│ │ Application │ │ │ │ Application │ │
│ ├─────────────────┤ │ │ ├─────────────────┤ │
│ │ Guest OS │ │ │ │ Dependencies │ │
│ │ (full kernel) │ │ │ ├─────────────────┤ │
│ ├─────────────────┤ │ │ │ Container │ │
│ │ Hypervisor │ │ │ │ Runtime │ │
│ ├─────────────────┤ │ │ ├─────────────────┤ │
│ │ Host OS │ │ │ │ Host OS │ │
│ └─────────────────┘ │ │ │ Kernel (shared)│ │
└───────────────────────┘ │ └─────────────────┘ │
└───────────────────────┘
| Característica | máquina virtual | Recipiente |
|---|---|---|
| Tiempo de arranque | Minutos | Milisegundos |
| Tamaño | GB | MB |
| Sobrecarga del sistema operativo | SO completo por VM | Núcleo compartido |
| Aislamiento | Fuerte (nivel de hardware) | Nivel de proceso |
| Actuación | Casi nativo | Casi nativo |
| Portabilidad | Bien | Excelente |
| Densidad | Bajo (10-100 por host) | Alto (100-1000 por host) |
Docker: la plataforma de contenedores
Conceptos clave
| Concepto | Descripción |
|---|---|
| Imagen | Una plantilla de solo lectura con instrucciones para crear un contenedor |
| Recipiente | Una instancia ejecutable de una imagen. |
| archivo Docker | Un archivo de texto con instrucciones para construir una imagen. |
| Registro | Almacenamiento y distribución de imágenes (Docker Hub, ECR, GCR) |
| Volumen | Almacenamiento de datos persistente fuera del sistema de archivos contenedor |
| Red | Comunicación entre contenedores y el mundo exterior. |
| Componer | Definir y ejecutar aplicaciones de múltiples contenedores |
Mejores prácticas de Dockerfile
# 1. Use specific base images (not 'latest')
FROM node:20-alpine AS builder
# 2. Set working directory
WORKDIR /app
# 3. Copy dependency files first (leverage layer caching)
COPY package*.json ./
RUN npm ci --production
# 4. Copy application code last
COPY . .
# 5. Use multi-stage builds
FROM node:20-alpine AS production
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
# 6. Run as non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
# 7. Expose only necessary ports
EXPOSE 3000
# 8. Use exec form of CMD
CMD ["node", "dist/server.js"]
Hoja de referencia de comandos de Docker
# Build image
docker build -t myapp:1.0 .
# Run container
docker run -d --name myapp -p 3000:3000 myapp:1.0
# Execute command in running container
docker exec -it myapp bash
# View logs
docker logs -f myapp
# List containers
docker ps -a
# Stop and remove
docker stop myapp && docker rm myapp
# Volumes (persistent data)
docker volume create data-volume
docker run -v data-volume:/app/data myapp:1.0
# Compose (multi-service)
docker compose up -d
docker compose logs -f
docker compose down
Redes acoplables
# docker-compose.yml
version: '3.8'
services:
web:
image: myapp:latest
ports:
- "3000:3000"
networks:
- frontend
- backend
depends_on:
- api
- db
api:
image: api:latest
networks:
- backend
environment:
- DB_HOST=db
db:
image: postgres:16-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
networks:
frontend:
backend:
volumes:
postgres_data:
secrets:
db_password:
file: ./secrets/db_password.txt
Kubernetes: orquestación de contenedores
Kubernetes (K8s) automatiza la implementación, el escalado y la gestión de aplicaciones en contenedores en un clúster.
Arquitectura
┌──────────────────────────────────────────────┐
│ Kubernetes Control Plane │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ API │ │ Scheduler│ │ Controller │ │
│ │ Server │ │ │ │ Manager │ │
│ └──────────┘ └──────────┘ └──────────────┘ │
│ ┌─────────────────────────────────────────┐│
│ │ etcd (distributed key-value store) ││
│ └─────────────────────────────────────────┘│
└─────────────────┬────────────────────────────┘
│
┌─────────────────▼────────────────────────────┐
│ Worker Nodes │
│ ┌──────────────────────────────────────────┐│
│ │ Node 1 ││
│ │ ┌──────┐ ┌──────┐ ┌──────┐ ││
│ │ │ Pod │ │ Pod │ │ Pod │ ││
│ │ └──────┘ └──────┘ └──────┘ ││
│ │ ┌────────────────────────────────────┐ ││
│ │ │ kubelet ││ kube-proxy ││ container │ ││
│ │ │ ││ ││ runtime │ ││
│ │ └────────────────────────────────────┘ ││
│ └──────────────────────────────────────────┘│
│ ┌──────────────────────────────────────────┐│
│ │ Node 2 (same structure) ││
│ └──────────────────────────────────────────┘│
└──────────────────────────────────────────────┘
Objetos principales de Kubernetes
Pod: unidad desplegable más pequeña
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp-container
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
Implementación: gestión declarativa de pods
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0
ports:
- containerPort: 3000
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 3
periodSeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
Servicio: acceso estable a la red
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 3000
protocol: TCP
type: ClusterIP # Internal access only
---
# For external access:
apiVersion: v1
kind: Service
metadata:
name: myapp-loadbalancer
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 3000
type: LoadBalancer
Ingreso: enrutamiento HTTP/HTTPS
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
ConfigMap y secreto: configuración
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: production
DB_HOST: postgres-service
LOG_LEVEL: info
---
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
DB_PASSWORD: c3VwZXJzZWNyZXQ= # base64 encoded
Implementación de una aplicación
# Apply configurations
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
# Check status
kubectl get pods
kubectl get deployments
kubectl get services
kubectl get ingress
# View logs
kubectl logs -f deployment/myapp-deployment
# Scale
kubectl scale deployment/myapp-deployment --replicas=5
# Rollout update
kubectl set image deployment/myapp-deployment myapp=myapp:2.0
kubectl rollout status deployment/myapp-deployment
# Rollback if needed
kubectl rollout undo deployment/myapp-deployment
Funciones avanzadas de Kubernetes
Escalador automático de pods horizontales (HPA)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp-deployment
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
Volúmenes persistentes
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard
---
apiVersion: v1
kind: Pod
metadata:
name: postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgres-storage
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: data-claim
Espacios de nombres
# Create namespaces for environment isolation
kubectl create namespace dev
kubectl create namespace staging
kubectl create namespace production
# Deploy to specific namespace
kubectl apply -f deployment.yaml -n production
# Resource quotas per namespace
kubectl create quota prod-quota --hard=cpu=40,memory=80Gi,pods=50 -n production
Docker versus Kubernetes: cuándo usar qué
| Guión | Docker solo | Agregar Kubernetes |
|---|---|---|
| Desarrollo local | ✅ Sí | ❌ Exceso |
| Implementación de un único servidor | ✅ Sí | ❌ Exceso |
| 2-3 microservicios | ✅ Composición acoplable | ❌ Generalmente exagerado |
| Se requiere alta disponibilidad | ❌ Conmutación por error manual | ✅ Autocuración |
| Se necesita escalado automático | ❌ manuales | ✅ HPA |
| Clúster de múltiples nodos | ❌ Limitado | ✅ Incorporado |
| Actualizaciones continuas | ❌ manuales | ✅ Incorporado |
| Implementaciones canarias | ❌ Complejo | ✅ Soporte nativo |
| Multinube | ❌ No portátil | ✅ Portátil |
Marco de decisión:
- Comience con Docker: siempre. Los contenedores son la base.
- Utilice Docker Compose: para desarrollo local, CI e implementaciones de host único.
- Adopte Kubernetes cuando: Necesita HA, escalamiento, múltiples nodos u orquestación compleja.
- Utilice Kubernetes administrado (EKS, AKS, GKE): evite la autoadministración del plano de control.
Mejores prácticas
Construcción de imágenes
- Utilice etiquetas de imagen base específicas (
node:20-alpine, nonode:latest). - Implemente compilaciones de varias etapas para minimizar el tamaño de la imagen.
- Escanee imágenes en busca de vulnerabilidades:
docker scan myapp:1.0. - Imágenes de signos:
signo de cosign --key cosign.key myapp:1.0.
Seguridad
- Ejecute contenedores como usuarios no root.
- Establezca sistema de archivos raíz de solo lectura:
readOnlyRootFilesystem: true. - Utilice secretos para datos confidenciales, no para variables de entorno.
- Implemente políticas de red para restringir el tráfico entre pods.
- Habilite RBAC para el acceso a la API de Kubernetes.
Gestión de recursos
- Establezca siempre solicitudes y límites de recursos.
- Utilice cuotas de recursos por espacio de nombres.
- Implemente HPA para escalado automático.
- Utilice PodDisruptionBudget para conocer la disponibilidad durante el mantenimiento.
Monitoreo y observabilidad
# Sidecar pattern for logging
spec:
containers:
- name: app
image: myapp:latest
- name: log-collector
image: fluentd:latest
volumeMounts:
- name: logs
mountPath: /var/log/app
Canalización de CI/CD
# GitHub Actions — Build + Deploy to Kubernetes
name: CI/CD
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t registry.example.com/myapp:${{ github.sha }} .
- name: Push to registry
run: docker push registry.example.com/myapp:${{ github.sha }}
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/myapp-deployment \
myapp=registry.example.com/myapp:${{ github.sha }}
El ecosistema
| Categoría | Herramientas |
|---|---|
| Tiempo de ejecución del contenedor | Docker, en contenedor, CRI-O |
| Orquestación | Kubernetes, Nomad, Docker Swarm |
| Administrador de paquetes | Timón, personalizar |
| Malla de servicio | Istio, Linkerd, Cilio |
| Escucha | Prometeo + Grafana, Datadog |
| Explotación florestal | ELK Stack, Grafana Loki, Fluentd |
| Seguridad | Trivy, Falco, OPA/Gatekeeper, Kyverno |
| GitOps | ArgoCD, flujo |
| Herramientas para desarrolladores | Skaffold, Inclinación, DevSpace |
| Almacenamiento | Torre/Ceph, Longhorn, Portworx |
| Sin servidor en K8 | Knativo, OpenFaaS, KEDA |
Conclusión
Docker y Kubernetes juntos proporcionan una plataforma poderosa para crear, implementar y escalar aplicaciones modernas:
- Comience con Docker: contenedorice aplicaciones, domine Dockerfiles y Compose.
- Conozca los fundamentos de Kubernetes: pods, implementaciones, servicios, ConfigMaps.
- Utilice Kubernetes administrado: deje que los proveedores de la nube se encarguen del plano de control.
- Adopte GitOps: ArgoCD o Flux para implementaciones declarativas con control de versiones.
- Invierta en observabilidad: el monitoreo, el registro y el rastreo son esenciales a escala.
La inversión en el aprendizaje de la contenerización y la orquestación rinde dividendos en términos de confiabilidad de la implementación, eficiencia operativa y portabilidad de las aplicaciones entre entornos.
Artículos destacados

6 patrones de programación que aprendí de ingenieros senior

Crea un asistente privado de notas con IA
Convierte notas Markdown en un asistente consultable sin exponer borradores privados.

Automatiza la extracción de datos de facturas con OCR
Crea un flujo que lee facturas, extrae campos y marca valores dudosos para revisión.
Comentarios
0 comentariosTodavía no hay comentarios aprobados. Las respuestas nuevas pueden esperar moderación.