[{"data":1,"prerenderedAt":231},["ShallowReactive",2],{"seo-verification":3,"blog-checklist-docker-compose-en-produccion-ma-es":6,"promo-bar-likely":230},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-checklist-docker-compose-en-produccion-ma-es",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":29,"intro":32,"sections":33,"ctaTitle":171,"ctaBody":172,"ctaButton":173,"ctaUrl":174,"relatedPosts":175},229,"checklist-docker-compose-en-produccion",{"fr":12,"en":13,"ar":14,"es":10},"docker-compose-production-checklist","docker-compose-in-production-10-point-checklist","docker-compose-في-الإنتاج-قائمة-التحقق-من-10-نقاط","Docker Compose en producción: checklist de 10 puntos","Docker Compose en producción: 10 ajustes, health checks, secretos, rollback, solución de errores y paso de docker-compose v1 a docker compose en Ubuntu 26.04.",12,1,false,"2026-08-06T00:00:00+00:00","2026-10-23T13:27:09+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},3,"Despliegue","deploiement","bg-success\u002F10 text-success",[28],{"id":23,"name":24,"slug":25,"color":26,"icon":25},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg","Un archivo docker-compose.yml que funciona en su equipo no sobrevive tal cual a la producción. Reinicio tras un reboot, límites de recursos, secretos, rotación de logs: son ajustes ausentes por defecto que provocan averías silenciosas una vez el servicio está expuesto. Esta checklist reúne los 10 parámetros que hay que controlar antes de desplegar una stack Compose en un VPS, y después los health checks, los secretos, el rollback y la solución de errores. También cubre el paso de `docker-compose` a `docker compose`, que la actualización a Ubuntu 26.04 obliga a resolver.",[34,38,52,55,89,137,140,150,153,156,159,162,165,168],{"type":35,"title":36,"body":37},"h2","Por qué una checklist antes de producción","Docker Compose se diseñó para el desarrollo: sus valores por defecto priorizan la simplicidad, no la robustez. Un contenedor no se reinicia tras un reinicio del host, sus logs crecen sin límite, puede consumir toda la RAM de la máquina y escucha en todas las interfaces de red. En desarrollo, ninguno de estos comportamientos supone un problema. En producción, esos ajustes ausentes se convierten en incidentes: disco lleno a las tres de la madrugada, base de datos perdida tras un `docker compose down`, servicio inaccesible tras un corte de corriente. La buena noticia: endurecer una stack Compose no exige reescribirla, solo una decena de añadidos concretos. Repase cada punto antes de publicar y su servicio aguantará la carga y los reinicios sin vigilancia constante.",{"type":39,"title":40,"items":41},"ul","Los 10 puntos de un vistazo",[42,43,44,45,46,47,48,49,50,51],"**restart: unless-stopped** — el contenedor se reinicia tras un reinicio del host o un fallo","**healthcheck** — Docker detecta un contenedor bloqueado y permite reinicios progresivos","**límites de CPU\u002Fmemoria** — un servicio desbocado no puede asfixiar a sus vecinos","**secretos via .env o Docker secrets** — nunca una contraseña en texto plano en el Compose","**volúmenes con nombre** — los datos sobreviven a un `docker compose down`","**rotación de logs** — `max-size` y `max-file` evitan que el disco se llene","**aislamiento de red** — separe `frontend` y `backend`, no exponga todo en el bridge por defecto","**binding de puertos** — `127.0.0.1:PORT` detrás de un proxy inverso, no `0.0.0.0`","**tags de imagen fijados** — una versión o digest, nunca `latest`","**depends_on con condición** — `service_healthy` evita las carreras de arranque",{"type":35,"title":53,"body":54},"Requisitos previos","Necesita un VPS con Docker Engine y el plugin Compose v2. El comando es `docker compose`, sin guion: compruébelo con `docker compose version`, porque la sintaxis `deploy.resources` fuera de Swarm exige Compose v2 (el antiguo `docker-compose` se trata más abajo). Controle también el motor con `docker version`. Docker Engine 29.7.2 corrige \u003Ca href=\"https:\u002F\u002Fwww.imperva.com\u002Fblog\u002Fcopyescape-docker-vulnerability-cve-2026-17106\u002F\">CVE-2026-17106\u003C\u002Fa> (CopyEscape), una race condition de `docker cp` divulgada el 10 de agosto de 2026: un contenedor no fiable puede sobrescribir con ella un archivo del host, incluido el binario `runc`. En los equipos de trabajo, el parche llegó con Docker Desktop 4.86.0. Mientras no actualice, no ejecute `docker cp` desde un contenedor cuyo contenido no controla. Guarde el proyecto en una carpeta dedicada (`\u002Fopt\u002Fmiapp`), con un `.env` en `chmod 600`. Prevea un proxy inverso delante — Traefik, Caddy o Nginx —, porque el binding de puertos supone que el tráfico público nunca llega a sus contenedores, y versione el archivo Compose.",{"type":56,"title":57,"steps":58},"steps","Los 10 pasos en detalle",[59,62,65,68,71,74,77,80,83,86],{"title":60,"body":61},"1. Política de reinicio","Añada `restart: unless-stopped` a cada servicio. El contenedor se reinicia tras un crash o reinicio del host, pero permanece detenido si usted lo paró voluntariamente. Evite `restart: always` que relanzaría incluso un contenedor que desea mantener parado, y prefiera `unless-stopped` para servicios de aplicación y `on-failure` para tareas puntuales.",{"title":63,"body":64},"2. Healthcheck","Declare un bloque `healthcheck:` con un `test` (p. ej. `curl -f http:\u002F\u002Flocalhost:8080\u002Fhealth || exit 1`), un `interval` (frecuencia de comprobación, p. ej. `30s`), un `timeout` (p. ej. `10s`) y `retries` (p. ej. `3`). Añada también `start_period: 40s` para servicios que tardan en arrancar, para no marcarlos `unhealthy` durante la inicialización. Docker marca entonces el contenedor `healthy` o `unhealthy`, permitiendo a los demás servicios reaccionar mediante `depends_on: condition: service_healthy`.",{"title":66,"body":67},"3. Límites de recursos","Bajo `deploy.resources.limits`, fije `cpus` y `memory` (p. ej. `memory: 512M`). Sin límite, un servicio con fugas puede consumir toda la RAM y hacer que el OOM killer mate a los demás. Añada también `reservations` para garantizar un mínimo en el arranque.",{"title":69,"body":70},"4. Secretos fuera del archivo","Nunca ponga una contraseña en texto plano en el YAML. Referenciarlos mediante `env_file: .env` o `${VARIABLE}`, o use el mecanismo `secrets:` de Docker que monta el secreto como archivo en `\u002Frun\u002Fsecrets\u002F` dentro del contenedor, fuera del alcance de `docker inspect`. Añada `.env` a su `.gitignore`.",{"title":72,"body":73},"5. Volúmenes con nombre","Declare sus datos en volúmenes con nombre con un driver explícito en lugar de bind-mounts anónimos. Un volumen con nombre sobrevive a `docker compose down`; solo `down -v` lo elimina. Documente cada volumen y asócielo a una estrategia de restauración probada.",{"title":75,"body":76},"6. Rotación de logs","Añada un bloque `logging:` con `driver: json-file` y opciones `max-size: \"10m\"` y `max-file: \"3\"`. Sin esto, los logs de un contenedor verboso llenan el disco hasta el fallo. Aplíquelo a cada servicio.",{"title":78,"body":79},"7. Aislamiento de red","Cree redes con nombre — una `frontend` para lo expuesto, una `backend` para la base de datos — y adjunte cada servicio solo a las redes que necesita. Añada `internal: true` a la red `backend` para impedir cualquier acceso desde el host o Internet, incluso ante un error de configuración de puertos.",{"title":81,"body":82},"8. Binding de puertos","Detrás de un proxy inverso, publique en `127.0.0.1:8080:8080` y no en `8080:8080` (equivalente a `0.0.0.0`). Docker modifica directamente las reglas iptables y puede saltarse UFW — el binding en `127.0.0.1` es la única garantía fiable en Compose.",{"title":84,"body":85},"9. Tags de imagen fijados","Sustituya `image: postgres:latest` por una versión precisa (`postgres:16.3`) o, mejor, por un digest. Combine con `pull_policy: missing` para un comportamiento predecible: Compose solo descarga una imagen nueva si está ausente en local.",{"title":87,"body":88},"10. Orden de arranque","Use `depends_on` con `condition: service_healthy` para que un servicio no espere solo el arranque sino la disponibilidad real de su dependencia. Para servicios sin healthcheck nativo, puede usar `condition: service_started` combinado con un script de espera (`wait-for-it.sh` o `dockerize`).",{"type":90,"title":91,"headers":92,"rows":96},"comparison","Valores por defecto de dev frente a ajustes de producción",[93,94,95],"Parámetro","Por defecto en dev","Recomendado en prod",[97,101,105,109,113,117,121,125,129,133],[98,99,100],"restart","no","unless-stopped",[102,103,104],"healthcheck","ausente","definido con interval y retries",[106,107,108],"memoria","sin restricción","límite fijado (p. ej. 512M)",[110,111,112],"secretos","texto plano posible",".env o Docker secrets",[114,115,116],"volúmenes","anónimos","con nombre y driver",[118,119,120],"logs","sin límite","max-size + max-file",[122,123,124],"red","bridge por defecto","frontend \u002F backend separados",[126,127,128],"puertos","0.0.0.0","127.0.0.1 detrás del proxy",[130,131,132],"imagen","latest","versión o digest fijado",[134,135,136],"depends_on","solo arranque","condition: service_healthy",{"type":35,"title":138,"body":139},"docker-compose o docker compose: la ruptura de Ubuntu 26.04","Dos herramientas llevan casi el mismo nombre. `docker-compose`, con guion, es Compose v1, escrito en Python: su repositorio lo declara al final de su vida útil desde la disponibilidad general de Compose v2, anunciada por Docker el 26 de abril de 2022. `docker compose`, con un espacio, es Compose v2, escrito en Go e integrado en la CLI de Docker como plugin. Ubuntu 26.04 completa la transición: el paquete `docker-compose` ya no está en el archivo desde Ubuntu 25.10, y el paquete `docker-compose-v2` solo instala el plugin, en `\u002Fusr\u002Flibexec\u002Fdocker\u002Fcli-plugins\u002F`. Tras la actualización, cualquier script que siga llamando al nombre antiguo se detiene en `docker-compose: command not found`. En la CI, GitHub sacó Compose v1 de sus runners alojados el 9 de julio de 2024, y pasa `ubuntu-latest` a Ubuntu 26.04 entre el 19 de octubre y el 19 de noviembre de 2026: conviene revisar un workflow que instalaba `docker-compose` a mano. Hay dos diferencias de comportamiento documentadas. Los nombres de contenedor usan un guion en lugar de un guion bajo (`miapp-web-1` frente a `miapp_web_1`), salvo con `--compatibility`. Y la clave `version:` se ignora, con la advertencia «the attribute `version` is obsolete, it will be ignored».",{"type":39,"title":141,"items":142},"Migrar sus scripts y añadir un shim",[143,144,145,146,147,148,149],"**Inventario** — `grep -rnE 'docker-compose( |$)' \u002Fopt \u002Fetc\u002Fcron* \u002Fetc\u002Fsystemd ~\u002F.bashrc` lista las llamadas que hay que corregir.","**Scripts y Makefile** — sustituya el guion por un espacio (`docker compose up -d`); los subcomandos habituales no cambian.","**cron y systemd** — llame a `\u002Fusr\u002Fbin\u002Fdocker compose` con ruta absoluta, porque cron se ejecuta con un `PATH` reducido.","**GitHub Actions** — pruebe sus workflows con `runs-on: ubuntu-26.04` antes del cambio, o fije `ubuntu-24.04` mientras los corrige, como recomienda GitHub.","**Shim temporal** — un archivo ejecutable `\u002Fusr\u002Flocal\u002Fbin\u002Fdocker-compose` de dos líneas, `#!\u002Fbin\u002Fsh` y luego `exec docker compose \"$@\"`, recoge las llamadas olvidadas. Docker mantiene también `compose-switch`, que traduce la sintaxis v1 a v2.","**Nombres de contenedor** — sustituya los `docker exec miapp_web_1` escritos a mano por `docker compose exec web`, que no depende del separador.","**Verificación** — `docker compose version` responde, `docker compose config` pasa sin advertencias, `command -v docker-compose` solo apunta al shim.",{"type":35,"title":151,"body":152},"Health checks avanzados: supervisar el estado real del servicio","Un health check bien configurado va más allá de un simple `curl`: mide el estado funcional del servicio, no solo su disponibilidad de red. Para una API HTTP, pruebe un endpoint ligero (`\u002Fhealth` o `\u002Fready`) que devuelva 200 solo si la conexión a la base de datos está establecida. Para PostgreSQL, use `pg_isready -U postgres`. Para Redis, basta con `redis-cli ping`. Compruebe el estado de sus contenedores con `docker compose ps`: la columna `STATUS` muestra `healthy`, `unhealthy` o `starting`. Un contenedor atascado en `starting` más allá del `start_period` indica un problema de inicialización — consulte `docker compose logs service`. El parámetro `start_period` define una ventana de gracia durante la cual los fallos no cuentan en los `retries`, imprescindible para servicios que necesitan tiempo para migrar su esquema.",{"type":35,"title":154,"body":155},"Secretos Docker sin Swarm: montar archivos en \u002Frun\u002Fsecrets\u002F","Fuera de Swarm, Compose acepta secretos de tipo archivo. Declare el secreto en la sección `secrets:` de nivel raíz, apuntando a un archivo local (`file: .\u002Fsecrets\u002Fdb_password.txt`), y referéncielo en el servicio con `secrets: [db_password]`. Docker monta ese archivo en solo lectura en `\u002Frun\u002Fsecrets\u002Fdb_password`: la aplicación lo lee como un archivo normal, y su valor no aparece ni en las variables de entorno que muestra `docker inspect` ni en los logs. Para rotarlo, versione el secreto: cree `db_password_v2` junto a `db_password_v1`, haga que el servicio lea `v2`, redespliéguelo solo con `docker compose up -d --no-deps service` y elimine `v1` una vez validado el despliegue. La interrupción se limita a recrear ese contenedor, y el secreto anterior sigue disponible para volver atrás.",{"type":35,"title":157,"body":158},"Rollback: volver atrás tras un despliegue fallido","El rollback de una stack Compose se prepara antes del despliegue, no después del incidente. Mantenga la imagen anterior etiquetada y disponible en local: añada un tag explícito `miapp:stable` antes de cada actualización. Para volver atrás, restablezca el tag anterior en el archivo Compose (o en el `.env` si la versión es una variable) y relance `docker compose up -d`. Los volúmenes no se ven afectados por un cambio de imagen, lo que hace rápido el rollback aplicativo; una migración de esquema, en cambio, necesita su migración inversa lista antes del despliegue. Para publicaciones críticas, separe `docker-compose.yml` (versión estable) y `docker-compose.override.yml` (versión candidata): `docker compose -f docker-compose.yml up -d` ignora el override y vuelve al estado estable.",{"type":160,"body":161},"tip","Pruebe siempre su stack endurecida en local antes de llevarla a producción: `docker compose config` para validar la sintaxis, luego `docker compose up` y simule un reboot con `docker compose restart`. Verifique que los contenedores vuelven `healthy` y que los datos persisten tras un `down` seguido de un `up`.",{"type":35,"title":163,"body":164},"Solución de problemas: 6 errores comunes y sus soluciones","**`docker: unknown command: docker compose`**: el plugin Compose no está instalado. En Ubuntu, instale `docker-compose-v2` desde el archivo, o `docker-compose-plugin` si Docker viene del repositorio oficial de Docker, y compruebe con `docker compose version`. **`network not found`**: tras un `docker compose down`, las redes con nombre se eliminan. Solución: declare las redes compartidas como `external: true` o sincronice el reinicio de las stacks dependientes. **`port is already in use`**: otro proceso ocupa el puerto. Identifíquelo con `ss -tlnp | grep :PORT` y deténgalo antes de relanzar. **OOM (Out Of Memory)**: el kernel mata un contenedor sin aviso — busque `OOMKilled: true` en `docker inspect container_id`. Aumente el límite de memoria o identifique la fuga con `docker stats`. **`permission denied on volume`**: el proceso del contenedor corre con un UID sin acceso al directorio montado. Compruebe el UID con `docker compose exec service id` y ajuste los permisos o añada `user: \"UID:GID\"`. **Contenedor reiniciándose en bucle**: `docker compose logs --tail=50 service` revela el error de arranque. Causas más frecuentes: variable de entorno ausente, archivo de configuración no encontrado o dependencia no lista.",{"type":35,"title":166,"body":167},"Copias de seguridad de volúmenes sin corrupción","Copiar archivos de un volumen PostgreSQL o MySQL **en caliente** con `rsync` o `tar` produce casi siempre una copia corrupta. La regla es **hacer siempre un dump SQL antes del snapshot del volumen**: `pg_dump` o `mysqldump` producen un estado coherente. Herramientas como \u003Ca href=\"https:\u002F\u002Fpistack.xyz\u002Fposts\u002F2026-05-11-self-hosted-docker-volume-backup-offen-nautical-loomchild-guide\u002F\">Restic y Offen Docker Backup\u003C\u002Fa> automatizan este proceso. Documente cada volumen con nombre y asócielo a una estrategia de restauración probada.",{"type":35,"title":169,"body":170},"Conclusión","Estos diez ajustes transforman un archivo Compose de desarrollo en una stack capaz de sobrevivir a reinicios, picos de carga y noches sin supervisión. Los health checks, los secretos montados como archivo, un rollback preparado y el paso completo a `docker compose` completan esta base. Nada de esto requiere una herramienta adicional: todo cabe en el YAML y los scripts que ya tiene. Repase la checklist antes de cada publicación, por ejemplo con una revisión de `docker compose config` integrada en el despliegue. Después podrá añadir un proxy inverso como Traefik o Caddy, o una capa de orquestación como Coolify.","Despliegue su stack Compose en producción","Un VPS ServOrbit le da el acceso root, la RAM y el control de red necesarios para hacer funcionar una stack Docker Compose endurecida. Elija su configuración y despliegue en unos minutos.","Desplegar en un VPS ServOrbit","\u002Fvps-cloud",[176,192,212],{"id":177,"slug":178,"slugs":179,"title":183,"excerpt":184,"readTime":185,"views":23,"isPinned":19,"noindex":19,"publishedAt":186,"updatedAt":187,"category":188,"categories":189,"featuredImage":29,"bgImage":30,"posterImage":191,"relatedSolution":29},38,"desplegar-con-traefik",{"fr":180,"en":181,"ar":182,"es":178},"deployer-avec-traefik","deploy-your-applications-with-traefik-on-a-vps","انشر-تطبيقاتك-باستخدام-traefik-على-خادم-vps","Desplegar sus aplicaciones con Traefik en un VPS","Despliegue Traefik como reverse proxy en su VPS: enrutamiento automático de los contenedores Docker, certificados SSL Let's Encrypt y balanceo de carga.",11,"2026-05-13T00:00:00+00:00","2026-11-08T01:13:13+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[190],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fdeployer-avec-traefik-poster.svg",{"id":193,"slug":194,"slugs":195,"title":199,"excerpt":200,"readTime":201,"views":202,"isPinned":19,"noindex":19,"publishedAt":203,"updatedAt":204,"category":205,"categories":206,"featuredImage":29,"bgImage":30,"posterImage":208,"relatedSolution":209},39,"desplegar-con-caddy",{"fr":196,"en":197,"ar":198,"es":194},"deployer-avec-caddy","deploy-your-applications-with-caddy-on-a-vps","انشر-تطبيقاتك-باستخدام-caddy-على-خادم-vps","Caddy como reverse proxy en VPS: guía completa","Instala y configura Caddy como reverse proxy en tu VPS: HTTPS automático con Let's Encrypt, múltiples apps, seguridad y solución de errores comunes.",8,4,"2026-05-12T00:00:00+00:00","2026-09-25T23:43:04+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[207],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fdeployer-avec-caddy-poster.svg",{"categorySlug":210,"appSlug":211},"despliegue-de-aplicaciones-devops","caddy",{"id":213,"slug":214,"slugs":215,"title":219,"excerpt":220,"readTime":17,"views":221,"isPinned":19,"noindex":19,"publishedAt":222,"updatedAt":223,"category":224,"categories":225,"featuredImage":29,"bgImage":30,"posterImage":227,"relatedSolution":228},41,"desplegar-aplicaciones-con-coolify-en-un-vps",{"fr":216,"en":217,"ar":218,"es":214},"deployer-avec-coolify","deploy-your-applications-with-coolify-on-a-vps","نشر-تطبيقاتك-باستخدام-coolify-على-vps","Desplegar sus aplicaciones con Coolify en un VPS","Despliegue Coolify en un VPS: instalación, configuración HTTPS, conexión Git, primera aplicación, bases de datos, copias de seguridad y diagnóstico.",2,"2026-05-10T00:00:00+00:00","2026-10-31T01:54:10+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[226],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fdeployer-avec-coolify-poster.svg",{"categorySlug":210,"appSlug":229},"coolify",true,1794270565338]