Docker Compose en producción: guía práctica para equipos pequeños en 2026
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
versionya no es obligatorio y de hecho es ignorado por las nuevas versiones de Docker Compose v2+. Puedes eliminarlo de tus archivos. - La directiva
depends_onahora 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. Usadocker 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\nElementos clave de la arquitectura
- Redes: separa la red interna (comunicación entre servicios) de la externa (proxy). El flag
internal: trueimpide 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_onsolo verifica que el contenedor ha arrancado, no que la aplicación esté lista. - Políticas de reinicio:
unless-stoppedes 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
- 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. - 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.
- 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\nActualizació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\nEl 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\"\nIntegració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\nNota 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\"\nPara 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:
- Usa
docker compose(plugin v2) sin el campoversionen el archivo - Separa las redes en internas y externas
- Nunca pases secretos mediante archivos
.enven el repositorio - Los health checks son obligatorios, no opcionales
- Fija las versiones de las imágenes, no uses
latest - Automatiza el despliegue mediante CI/CD desde el primer día
- 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í →