DevOps

Docker Compose en producción: guía práctica para equipos pequeños en 2026

Ruslan Ismailov Publicado 10 min de lectura
D

Introducción: Docker Compose en 2026 — vigente y relevante

Hace años que se habla de que Docker Compose está "obsoleto" y solo sirve para el desarrollo local. Sin embargo, en 2026 miles de startups y equipos pequeños lo utilizan con éxito en despliegues de producción. Y no es por desconocer las alternativas — es una elección consciente.

Docker Compose sigue siendo una herramienta relevante donde importan la simplicidad, la velocidad de iteración y el mínimo coste operativo. Kubernetes es más potente, pero esa potencia conlleva complejidad: formación del equipo, mantenimiento del clúster, configuración de RBAC, charts de Helm. Para un equipo de dos a cinco personas, esto suele ser excesivo.

En este artículo veremos cómo construir una infraestructura production-ready con Docker Compose: desde la arquitectura de archivos hasta CI/CD y monitoreo, y discutiremos honestamente cuándo es el momento de mirar hacia Kubernetes.

Docker Compose v2 vs v3: diferencias clave y qué usar ahora

Durante mucho tiempo existió confusión entre las versiones del esquema del archivo Compose (v2, v3) y las versiones de la herramienta en sí. En 2026 la situación se aclaró: Docker migró oficialmente a una especificación unificada, la Compose Specification, que reúne lo mejor de ambos mundos.

Qué cambió en la práctica

  • El campo version ya no es obligatorio y de hecho es ignorado por las nuevas versiones de Docker Compose v2+. Puedes eliminarlo de tus archivos.
  • La directiva depends_on ahora soporta condiciones (condition: service_healthy), convirtiéndola en una herramienta completa para controlar el orden de arranque.
  • Los secretos y configuraciones tienen soporte nativo — no solo para Swarm, sino también para Compose estándar.
  • El comando docker-compose (con guion, versión en Python) está obsoleto. Usa docker compose (el plugin escrito en Go) — es más rápido y se mantiene activamente.

La conclusión es simple: en 2026 escribe tus archivos según la Compose Specification sin el campo version y usa docker compose en lugar de docker-compose.

Arquitectura de un archivo Compose production-ready

Un buen archivo de producción no es simplemente una lista de servicios. Es la declaración de cómo debe comportarse tu aplicación bajo carga, ante fallos y durante actualizaciones.

Ejemplo de estructura base

services:\n  app:\n    image: registry.example.com/myapp:${APP_VERSION:-latest}\n    restart: unless-stopped\n    networks:\n      - internal\n      - proxy\n    environment:\n      - DATABASE_URL=${DATABASE_URL}\n    secrets:\n      - db_password\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8080/health\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n      start_period: 40s\n    depends_on:\n      db:\n        condition: service_healthy\n    deploy:\n      resources:\n        limits:\n          cpus: \"1.0\"\n          memory: 512M\n\n  db:\n    image: postgres:16-alpine\n    restart: unless-stopped\n    networks:\n      - internal\n    volumes:\n      - pg_data:/var/lib/postgresql/data\n    environment:\n      POSTGRES_PASSWORD_FILE: /run/secrets/db_password\n    secrets:\n      - db_password\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U postgres\"]\n      interval: 10s\n      timeout: 5s\n      retries: 5\n\n  redis:\n    image: redis:7-alpine\n    restart: unless-stopped\n    networks:\n      - internal\n    volumes:\n      - redis_data:/data\n    command: redis-server --appendonly yes\n\n  nginx:\n    image: nginx:alpine\n    restart: unless-stopped\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    networks:\n      - proxy\n    volumes:\n      - ./nginx/conf.d:/etc/nginx/conf.d:ro\n      - certbot_data:/etc/letsencrypt\n\nnetworks:\n  internal:\n    driver: bridge\n    internal: true\n  proxy:\n    driver: bridge\n\nvolumes:\n  pg_data:\n  redis_data:\n  certbot_data:\n\nsecrets:\n  db_password:\n    file: ./secrets/db_password.txt\n

Elementos clave de la arquitectura

  • Redes: separa la red interna (comunicación entre servicios) de la externa (proxy). El flag internal: true impide que los contenedores en esa red accedan a internet — una buena práctica para las bases de datos.
  • Volúmenes: usa siempre volúmenes con nombre para los datos que requieren persistencia. Nunca almacenes datos de producción en bind mounts.
  • Health checks: son obligatorios para cualquier servicio del que dependan otros. Sin ellos, depends_on solo verifica que el contenedor ha arrancado, no que la aplicación esté lista.
  • Políticas de reinicio: unless-stopped es un valor predeterminado razonable para producción. Reinicia el contenedor ante fallos, pero no lo toca si se detiene manualmente.
  • Límites de recursos: limita CPU y memoria. Sin límites, un servicio puede consumir todos los recursos del host.

Secretos y configuraciones: gestión segura de variables de entorno

Pasar secretos a través de variables de entorno en un archivo .env es el error más común. Estos archivos acaban en el repositorio, en los logs de CI y en el historial de comandos. En producción se necesita otro enfoque.

Niveles de gestión de secretos

  1. Docker Secrets (nativo): los archivos se montan en /run/secrets/ del contenedor. Están soportados en Compose estándar (no solo en Swarm). Se muestran en el ejemplo anterior.
  2. Almacenes externos: HashiCorp Vault, AWS Secrets Manager, Doppler. Los secretos se obtienen en el momento del despliegue y se pasan como archivos o mediante variables de entorno.
  3. Variables de entorno de CI/CD: GitLab CI, GitHub Actions y otros sistemas permiten almacenar secretos a nivel de proyecto. En el momento del despliegue se insertan en los lugares correspondientes.

Esquema práctico para un equipo pequeño

El esquema seguro mínimo: los secretos se almacenan en variables de GitLab/GitHub, durante el despliegue se escriben en archivos en el servidor y Compose los lee mediante el mecanismo de secrets. El archivo .env contiene solo configuración no sensible (nombres de imágenes, puertos, nombres de bases de datos) y puede estar en el repositorio.

# .env (seguro para commitear)\nAPP_VERSION=1.4.2\nDB_NAME=myapp_prod\nREDIS_MAX_MEMORY=256mb\n\n# secrets/db_password.txt (NO commitear, en .gitignore)\n# Creado por el script de despliegue desde las variables de CI/CD\n

Actualización de servicios sin tiempo de inactividad

Docker Compose no tiene rolling update integrado como Kubernetes. Pero el tiempo de inactividad cero es alcanzable con la arquitectura correcta.

Estrategia blue-green con nginx

El enfoque más sencillo: mantener el reverse proxy (nginx o Traefik) fuera y actualizar la aplicación con una breve conmutación:

# Actualización sin downtime\ndocker compose pull app\ndocker compose up -d --no-deps --build app\n

El flag --no-deps actualiza solo el servicio indicado sin reiniciar las dependencias. Docker primero arranca el nuevo contenedor, verifica que pasa el healthcheck y luego detiene el anterior. Con health check, el tiempo de inactividad se reduce a segundos.

Traefik como proxy inteligente

Para actualizaciones más fluidas, muchos equipos usan Traefik en lugar de Nginx. Traefik lee las etiquetas de los contenedores Docker y redirige automáticamente el tráfico hacia las instancias saludables:

  app:\n    image: registry.example.com/myapp:${APP_VERSION}\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.app.rule=Host(`example.com`)\"\n      - \"traefik.http.services.app.loadbalancer.healthcheck.path=/health\"\n

Integración con el pipeline de CI/CD

El despliegue automático mediante Docker Compose en CI/CD no es ciencia espacial. El esquema típico: construir la imagen → publicar en el registry → SSH al servidor → docker compose up.

Ejemplo de pipeline GitLab CI/CD

stages:\n  - build\n  - deploy\n\nbuild:\n  stage: build\n  script:\n    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .\n    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA\n  only:\n    - main\n\ndeploy:\n  stage: deploy\n  script:\n    - echo \"$DB_PASSWORD\" > secrets/db_password.txt\n    - export APP_VERSION=$CI_COMMIT_SHORT_SHA\n    - docker compose pull\n    - docker compose up -d --no-deps app\n    - docker compose exec app php artisan migrate --force\n  environment:\n    name: production\n  only:\n    - main\n

Nota importante: las migraciones de base de datos se ejecutan después de arrancar el contenedor, pero antes de conmutar el tráfico — este orden es crucial. Si usas Laravel u otro framework con sistema de migraciones, asegúrate de que sean idempotentes.

Rollback

Revertir en el mundo de Compose es trivial: basta con cambiar el tag de la imagen al anterior y repetir docker compose up. Fija los tags de las imágenes en variables y nunca uses latest en producción.

Monitoreo y logging de contenedores

"El monitoreo no es opcional en producción" — es una verdad manida pero cierta. Docker Compose no incluye monitoreo de serie, pero se integra con las soluciones más populares sin complicaciones.

Logging

Configura el driver de logging a nivel de servicio o globalmente en /etc/docker/daemon.json:

  app:\n    logging:\n      driver: \"json-file\"\n      options:\n        max-size: \"50m\"\n        max-file: \"5\"\n

Para logging centralizado: Loki + Grafana es una excelente opción para equipos pequeños. Promtail recopila los logs de los contenedores Docker y los envía a Loki. Todo el stack se levanta con el mismo Compose.

Métricas

El stack Prometheus + Grafana se ha convertido en el estándar de facto. Añade al archivo Compose:

  • cAdvisor — métricas de contenedores (CPU, RAM, red)
  • Node Exporter — métricas del host
  • Prometheus — recopilación y almacenamiento de métricas
  • Grafana — visualización

Todo el stack de monitoreo puede extraerse a un archivo docker-compose.monitoring.yml independiente y lanzarse con docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -d.

Alertas

Alertmanager (parte del ecosistema Prometheus) o el sencillo uptimerobot.com para verificaciones básicas de disponibilidad son suficientes para la mayoría de proyectos pequeños. Configura notificaciones en Slack o Telegram.

Cuándo migrar a Kubernetes: criterios honestos

Docker Compose es una excelente herramienta, pero tiene limitaciones reales. Esta es una lista honesta de señales de que es momento de mirar hacia Kubernetes:

Disparadores técnicos

  • Necesitas escala horizontal: quieres ejecutar 5, 10 o 50 réplicas de un servicio en diferentes máquinas. Compose funciona en un solo host. Docker Swarm es una opción intermedia, pero en 2026 su desarrollo se ha ralentizado.
  • Se requiere autoescalado: el HPA (Horizontal Pod Autoscaler) de Kubernetes reacciona automáticamente a la carga. En Compose hay que cambiar las réplicas manualmente.
  • Orquestación compleja: decenas de servicios con diferentes versiones, dependencias complejas y ciclos de despliegue independientes — Kubernetes con Helm es significativamente más conveniente.
  • Multi-región o multi-nodo: en cuanto surge la necesidad de varios servidores para una misma aplicación, Compose deja de ser suficiente.
  • SLA estrictos: si tu SLA es del 99,99%, necesitas mecanismos de recuperación automática, rolling updates sin downtime y circuit breakers — todo esto es nativo en Kubernetes.

Disparadores organizativos

  • El equipo ha crecido a más de 10 personas y hay varios equipos independientes
  • Existe un ingeniero DevOps/Platform dedicado
  • El número de microservicios supera los 15-20
  • Se necesita aislamiento de entornos (dev/staging/prod) con recursos diferenciados a nivel de clúster

Cuándo NO se necesita Kubernetes

Si tu monolito o conjunto de 3-5 servicios atiende a 10.000 usuarios al día en un solo servidor — Docker Compose lo gestiona perfectamente. La migración a Kubernetes añadirá como mínimo 2-4 semanas de configuración y costes operativos continuos. Ese tiempo es mejor invertirlo en el producto.

Conclusión

Docker Compose en 2026 es una herramienta madura y fiable para despliegues en producción de equipos pequeños. Con la arquitectura correcta — redes separadas, volúmenes con nombre, health checks, gestión de secretos e integración con CI/CD — garantiza el funcionamiento estable de las aplicaciones sin la complejidad operativa de Kubernetes.

Principios clave que conviene recordar:

  1. Usa docker compose (plugin v2) sin el campo version en el archivo
  2. Separa las redes en internas y externas
  3. Nunca pases secretos mediante archivos .env en el repositorio
  4. Los health checks son obligatorios, no opcionales
  5. Fija las versiones de las imágenes, no uses latest
  6. Automatiza el despliegue mediante CI/CD desde el primer día
  7. Añade monitoreo antes del primer incidente, no después

Kubernetes es una herramienta poderosa, pero su momento llega con la escala. No compliques las cosas antes de tiempo. Compose ofrece el 80% de las capacidades con el 20% de la complejidad — y para la mayoría de los equipos pequeños, esa es la proporción ideal.

Tecnologías

Etiquetas

Ruslan Ismailov

Desarrollador Senior Web / Backend. Desarrollador senior web/backend con 9 años de experiencia. Stack: PHP, Laravel, PostgreSQL, Redis, Docker, Kubernetes, REST, microservicios, CI/CD. Más sobre mí →