DEV Community

David Rodriguez
David Rodriguez

Posted on • Originally published at devopsfreelance.pro

Docker vs Kubernetes: Diferencias, Cuándo Usar Cada Uno y Cómo se Complementan

Docker y Kubernetes no son competidores: Docker crea y ejecuta contenedores, Kubernetes los orquesta en producción. Entender cuándo necesitas uno, otro, o ambos, es fundamental para cualquier ingeniero DevOps.

Docker y Kubernetes: Conceptos Diferentes

La pregunta "Docker vs Kubernetes" parte de una confusión habitual. No es una elección entre uno u otro en la mayoría de los casos. Son herramientas que operan en capas distintas:

  • Docker es una plataforma para crear, empaquetar y ejecutar contenedores
  • Kubernetes es un sistema para orquestar, escalar y gestionar contenedores en producción

Es como comparar un motor con un sistema de gestión de flotas. El motor (Docker) hace que el vehículo funcione. El sistema de flotas (Kubernetes) coordina cientos de vehículos.

Qué es Docker

Docker es la plataforma que popularizó los contenedores. Permite empaquetar una aplicación junto con todas sus dependencias en una imagen portable que se ejecuta de forma idéntica en cualquier máquina.

Componentes de Docker

Componente Función
Docker Engine Runtime que ejecuta contenedores
Dockerfile Receta para construir imágenes
Docker Image Paquete inmutable con app + dependencias
Docker Container Instancia en ejecución de una imagen
Docker Hub Registro público de imágenes
Docker Compose Orquestación local multi-contenedor

Ejemplo: Dockerizar una Aplicación

# Dockerfile multi-stage para app Node.js
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/server.js"]
Enter fullscreen mode Exit fullscreen mode
# Construir y ejecutar
docker build -t mi-app:1.0 .
docker run -d -p 3000:3000 --name mi-app mi-app:1.0
Enter fullscreen mode Exit fullscreen mode

Docker Compose para Desarrollo Local

Docker Compose permite definir aplicaciones multi-contenedor en un solo archivo:

# docker-compose.yml
services:
  api:
    build: ./api
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/mydb
      - REDIS_URL=redis://cache:6379
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
      interval: 5s
      timeout: 3s
      retries: 5

  cache:
    image: redis:7-alpine
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:
Enter fullscreen mode Exit fullscreen mode

Qué es Kubernetes

Kubernetes (K8s) es un sistema de orquestación de contenedores creado por Google y donado a la CNCF. Gestiona el despliegue, escalado, networking y disponibilidad de aplicaciones containerizadas en clusters de servidores.

Problemas que Kubernetes Resuelve

Cuando tienes una aplicación en producción con múltiples contenedores, necesitas responder preguntas como:

  • Si un contenedor muere, ¿quién lo reinicia?
  • Si hay más tráfico, ¿quién crea más instancias?
  • ¿Cómo distribuyo tráfico entre múltiples instancias?
  • ¿Cómo actualizo sin downtime?
  • ¿Cómo gestiono secretos y configuración?
  • ¿Cómo manejo el almacenamiento persistente?

Kubernetes responde todas estas preguntas.

Componentes de Kubernetes

Componente Función
Pod Unidad mínima de despliegue (1+ contenedores)
Deployment Gestiona réplicas de pods y rolling updates
Service Expone pods con IP estable y load balancing
Ingress Enrutamiento HTTP/HTTPS externo
ConfigMap/Secret Configuración y secretos externalizados
Namespace Aislamiento lógico de recursos
HPA Autoescalado basado en métricas
PersistentVolume Almacenamiento persistente

Ejemplo: Desplegar en Kubernetes

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mi-app
  labels:
    app: mi-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mi-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: mi-app
    spec:
      containers:
      - name: mi-app
        image: mi-registro/mi-app:1.0
        ports:
        - containerPort: 3000
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 10
          periodSeconds: 15
        readinessProbe:
          httpGet:
            path: /ready
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: url
---
apiVersion: v1
kind: Service
metadata:
  name: mi-app-service
spec:
  selector:
    app: mi-app
  ports:
  - port: 80
    targetPort: 3000
  type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: mi-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: mi-app
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
Enter fullscreen mode Exit fullscreen mode

Comparación Directa

Funcionalidad

Capacidad Docker (solo) Docker + Compose Kubernetes
Crear contenedores Si Si No (usa containerd/CRI-O)
Multi-contenedor local Manual Si Overkill
Auto-healing No No Si
Autoescalado No No Si (HPA/VPA/KEDA)
Load balancing No Limitado Si (Services + Ingress)
Rolling updates No Limitado Si (nativo)
Service discovery No DNS interno DNS + Services
Gestión de secretos No Variables de entorno Si (Secrets + external-secrets)
Multi-nodo No No Si (diseñado para clusters)
Storage persistente Volumes locales Volumes locales PV/PVC + CSI drivers

Complejidad

Aspecto Docker Kubernetes
Curva de aprendizaje Baja (horas/días) Alta (semanas/meses)
Configuración inicial Un comando Cluster completo
Operación día a día Simple Requiere expertise
Debugging Directo Múltiples capas
Costo operativo Bajo Alto (cluster + operadores)

Costos en Cloud

Escenario Docker (ECS Fargate) Kubernetes (EKS)
Costo base del servicio $0 ~$73/mes por cluster
3 servicios pequeños ~$30-50/mes ~$150-200/mes
10 servicios medianos ~$200-400/mes ~$400-600/mes
50+ microservicios ~$1,000-3,000/mes ~$1,500-4,000/mes
Equipo necesario 1-2 DevOps 2-4 DevOps/SRE

Cuándo Usar Solo Docker

Docker sin Kubernetes es suficiente cuando:

  • Aplicaciones simples: Un monolito o pocos servicios
  • Desarrollo local: Docker Compose para simular el entorno de producción
  • Equipos pequeños: 1-5 desarrolladores sin equipo de infraestructura dedicado
  • Tráfico predecible: Sin necesidad de autoescalado agresivo
  • Presupuesto limitado: No puedes justificar el costo de operar un cluster K8s
  • Servicios managed: Usar ECS Fargate, Cloud Run o Azure Container Instances

Ejemplo Real: Startup con 3 Microservicios

Arquitectura:
  API Gateway → Auth Service → Product Service → PostgreSQL

Infraestructura:
  AWS ECS Fargate (sin servidores que gestionar)
  ALB para load balancing
  RDS PostgreSQL managed

Costo mensual: ~$150-200
Equipo necesario: 1 DevOps part-time
Enter fullscreen mode Exit fullscreen mode

Cuándo Necesitas Kubernetes

Kubernetes se justifica cuando:

  • Muchos microservicios: 10+ servicios que necesitan coordinación
  • Autoescalado avanzado: Picos de tráfico impredecibles, escalado basado en métricas custom
  • Multi-cloud o híbrido: Portabilidad entre proveedores cloud
  • Equipo dedicado: Tienes DevOps/SRE que pueden operar el cluster
  • Requisitos de disponibilidad: SLAs exigentes (99.9%+)
  • Ecosistema rico: Necesitas service mesh, GitOps, operators personalizados

Ejemplo Real: Fintech con 40 Microservicios

Arquitectura:
  Ingress Controller (NGINX)
    → API Gateway (Kong)
      → 40 microservicios en pods
      → 3 bases de datos (RDS)
      → Redis cluster
      → Kafka (event streaming)

Infraestructura:
  AWS EKS (3 nodos m5.xlarge + autoscaling)
  ArgoCD para GitOps
  Prometheus + Grafana para observabilidad
  cert-manager para TLS automático

Costo mensual: ~$2,000-3,500
Equipo necesario: 2-3 DevOps/SRE dedicados
Enter fullscreen mode Exit fullscreen mode

Docker + Kubernetes: Cómo Trabajan Juntos

En la práctica, Docker y Kubernetes se complementan en un flujo continuo:

Developer escribe código
    ↓
Docker build (crear imagen)
    ↓
Docker push (subir a registro)
    ↓
Kubernetes pull (descargar imagen)
    ↓
Kubernetes deploy (crear pods)
    ↓
Kubernetes manage (escalar, heal, update)
Enter fullscreen mode Exit fullscreen mode

Pipeline CI/CD Completo

# GitHub Actions: build con Docker, deploy con Kubernetes
name: Build and Deploy
on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Login to ECR
        uses: aws-actions/amazon-ecr-login@v2

      - name: Build and push Docker image
        run: |
          docker build -t $ECR_REGISTRY/mi-app:$GITHUB_SHA .
          docker push $ECR_REGISTRY/mi-app:$GITHUB_SHA

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Update Kubernetes deployment
        run: |
          aws eks update-kubeconfig --name my-cluster
          kubectl set image deployment/mi-app \
            mi-app=$ECR_REGISTRY/mi-app:$GITHUB_SHA
          kubectl rollout status deployment/mi-app
Enter fullscreen mode Exit fullscreen mode

Alternativas a Kubernetes

Si Kubernetes es demasiado complejo para tu caso, considera estas alternativas:

Alternativa Descripción Cuándo Usarla
AWS ECS Fargate Contenedores managed sin servidores AWS-only, equipos pequeños
Google Cloud Run Contenedores serverless Tráfico variable, pay-per-request
Azure Container Apps Contenedores managed con Dapr Ecosistema Microsoft
Docker Swarm Orquestación simple integrada en Docker Clusters pequeños, baja complejidad
Nomad Orquestador de HashiCorp Multi-workload (containers + VMs)
Railway/Render PaaS con contenedores Startups, prototipos rápidos

Errores Comunes

Error 1: Usar Kubernetes para Todo

Kubernetes tiene un costo operativo significativo. Si tienes un monolito o 2-3 servicios, Docker Compose o ECS Fargate son más eficientes. No uses un cañón para matar una mosca.

Error 2: Ignorar Docker Compose

Docker Compose es la mejor herramienta para desarrollo local. Incluso si tu producción usa Kubernetes, tu entorno local debería usar Compose para que los desarrolladores sean productivos sin necesitar un cluster.

Error 3: No Definir Resource Limits

En Kubernetes, siempre define requests y limits de CPU y memoria. Sin ellos, un pod puede consumir todos los recursos del nodo y afectar otros servicios.

Error 4: Imágenes Docker Enormes

Usa multi-stage builds y base images Alpine o distroless. Una imagen de 1.5GB es un problema de seguridad y de performance. Consulta nuestra guía de optimización de imágenes Docker para más detalles.

Decisión Final: Diagrama de Flujo

¿Cuántos servicios tienes?
  ├─ 1-3 servicios → Docker + Compose + ECS/Cloud Run
  ├─ 4-10 servicios → Evalúa: ¿necesitas autoescalado avanzado?
  │   ├─ No → ECS Fargate o Cloud Run
  │   └─ Si → Kubernetes (managed: EKS/GKE/AKS)
  └─ 10+ servicios → Kubernetes (managed)
      └─ ¿Tienes equipo SRE/DevOps dedicado?
          ├─ Si → EKS/GKE/AKS
          └─ No → Considera contratar o usar PaaS
Enter fullscreen mode Exit fullscreen mode

Conclusión

Docker y Kubernetes no compiten: se complementan. Docker es la base para empaquetar aplicaciones en contenedores. Kubernetes agrega la capa de orquestación que necesitas cuando operas múltiples servicios en producción a escala.

La clave es elegir la complejidad adecuada para tu contexto. No adoptes Kubernetes porque es popular; adoptalo porque resuelve problemas reales que tienes hoy. Y si Docker solo o Docker con ECS/Cloud Run resuelven tu problema, esa es la mejor solución.

Para profundizar, consulta nuestra guía de virtualización y Linux para DevOps y cómo crear infraestructura inmutable con contenedores.

Top comments (0)