Por qué Docker Compose 5.5 recrea tus contenedores
Índice de contenidos
- Puntos clave
- Qué cambió en Docker Compose 5.5
- A quién afecta la recreación
- Cómo he reproducido la recreación
- Cómo saber qué contenedores se van a recrear
- Cuánto dura la recreación y cómo elegir el momento
- Qué hace pull_policy con daily, weekly y every_N
- Preguntas frecuentes
- ¿Puedo evitar la recreación sin quedarme en Compose 5.4?
- ¿Pierdo datos cuando Compose recrea un contenedor?
- ¿Por qué no se recrean mis contenedores después de actualizar?
- Conclusión
- Fuentes
Docker Compose 5.5 cambia el digest con el que decide si la imagen de un contenedor ha cambiado. Con el almacén de imágenes de containerd, los contenedores que Compose 2.40 o un up de 5.4 con descarga etiquetaron con el digest del índice se recrean una vez en el primer up, sin cambios reales. up –dry-run los señala antes.
Si has actualizado Docker Compose a la 5.5 y el primer docker compose up -d ha parado y vuelto a crear contenedores que no habías tocado, tu fichero no tiene la culpa. Compose 5.5.0 cambió el digest que guarda en cada contenedor para saber si su imagen ha cambiado, y con el almacén de imágenes de containerd el valor antiguo ya no coincide. Lo he reproducido con Compose 5.4.0, 5.5.0 y 5.5.1 sobre Docker Engine 29 en arm64. Aquí tienes a quién afecta, cómo saber qué contenedores se van a recrear antes de ejecutar nada y qué hace en realidad pull_policy: daily. La guía está disponible en inglés.
Puntos clave
- Compose 5.5.0, publicado el 17 de agosto de 2026, avisa en sus notas de que los contenedores existentes pueden recrearse en el primer
compose uptras actualizar. La última versión al escribir esto (16 de septiembre de 2026) es la 5.5.1, del 3 de septiembre. - Solo ocurre con el almacén de imágenes de containerd, el que Docker Engine 29 usa por defecto en instalaciones nuevas. Con overlay2 no se recreó nada en mis pruebas.
- Se recrean los contenedores cuya etiqueta
com.docker.compose.imageguarda el digest del índice multiplataforma: todos los que creó Compose v2.40.3 y los que la 5.4.0 creó en unupque descargó la imagen. docker compose up -d --dry-runcon la versión nueva lista los contenedores afectados sin tocarlos.config --hashno sirve, porque ese hash no cambia.- Con tres servicios pequeños, la recreación tardó 2,34 s de mediana y nginx dejó de responder durante 1,32 s.
- Con
pull_policy: dailyoevery_N,uprespeta la ventana y la 5.5 ya no recrea en cada ciclo. Undocker compose pullexplícito descarga siempre, diga lo que diga la nota de la versión.
Qué cambió en Docker Compose 5.5
Compose 5.5.0 rehízo la forma de decidir si la imagen de un contenedor ha cambiado. Cada contenedor que crea Compose lleva la etiqueta com.docker.compose.image con un digest de su imagen. En cada up, Compose compara ese valor con el de la imagen local y, si no coinciden, recrea el contenedor. Las notas de la versión 5.5.0 de Docker Compose[1] lo avisan con esta frase:
"Existing containers may be recreated the first time you run compose up after upgrading, as image digests are re-evaluated using the new logic."
El motivo está en el pull request #14011 de Docker Compose[2], de Guillaume Lours. Una imagen multiplataforma tiene tres identificadores posibles: el digest del índice (la lista de plataformas), el del manifiesto de tu plataforma y el de su configuración.
Hasta la 5.4, cada camino del código (la descarga, la construcción, la imagen ya presente) escribía el suyo, y con containerd no coincidían. Desde la 5.5 todos escriben el digest del manifiesto de tu plataforma. El propio pull request lo describe como "One-time recreate on first up after upgrading" y añade: "Subsequent runs are stable."

Las imágenes oficiales que usé en la prueba lo ilustran. El índice de redis:7.2-alpine lista 16 manifiestos, 8 de plataforma y 8 de atestación. Su digest es sha256:ccd6aa8d…, mientras que el manifiesto de linux/arm64 es sha256:efd8e95c…. Ese par es el que vi cambiar en la etiqueta del contenedor.
A quién afecta la recreación
Te afecta si tu Docker usa el almacén de imágenes de containerd y tus contenedores llevan el digest del índice. La documentación de Docker sobre el almacén de containerd[3] explica que es el almacén por defecto desde Docker Engine 29.0 en instalaciones nuevas. Un demonio actualizado desde una versión anterior sigue con overlay2 hasta que lo cambies. Para saber cuál usas, consulta el controlador de almacenamiento:
docker info -f '{{.Driver}} {{json .DriverStatus}}'
En mi máquina devuelve overlayfs [["driver-type","io.containerd.snapshotter.v1"]], que es containerd. Si ves overlay2, estás en el almacén clásico. Ahí la etiqueta guarda el identificador de la imagen, que no cambia de tipo, y ninguna de mis pruebas recreó nada. Estos son los cinco casos que probé:
| Cómo se creó el contenedor | Almacén | Primer up con 5.5 |
|---|---|---|
Compose 5.4.0, en un up que descargó la imagen |
containerd | Se recrea |
Compose 5.4.0, con otro up posterior |
containerd | Se queda |
| Compose v2.40.3, con o sin descarga | containerd | Se recrea |
Compose 5.4.0, en un up que descargó la imagen |
overlay2 | Se queda |
Servicio con build: creado por 5.4.0 |
containerd | Se queda |
La segunda fila tiene explicación. Compose 5.4.0 ya sufría el fallo que corrige la 5.5: tras un up que descarga imágenes, el siguiente up recreaba todos los contenedores sin motivo y dejaba escrito el digest del manifiesto. Si eso ya te pasó con la 5.4, la actualización no recrea nada más. Compose v2.40.3, en cambio, escribe siempre el digest del índice, así que todo lo que creó se recrea una vez.
Cómo he reproducido la recreación
Monté la prueba el 16 de septiembre de 2026 en un contenedor de desarrollo linux/arm64 con 18 núcleos y Docker Engine 29.5.2 con containerd. Para comparar almacenes añadí dos Docker-in-Docker 29.6.1, uno con containerd y otro con overlay2. El sistema traía Compose v2.40.3, así que descargué los binarios oficiales y los ejecuté desde su carpeta, sin tocar el complemento instalado. Cada versión publica su suma SHA-256 junto al binario:
v=5.5.1
base=https://github.com/docker/compose/releases/download/v$v
curl -sSLo docker-compose-$v $base/docker-compose-linux-aarch64
curl -sSL $base/docker-compose-linux-aarch64.sha256
sha256sum docker-compose-$v
chmod +x docker-compose-$v
./docker-compose-$v version
Las dos sumas coincidieron en las tres versiones (732e3a84… en la 5.5.1). Un detalle curioso: el binario de la versión 5.5.1 de Docker Compose[4] pesa 30,2 MB, frente a los 46,4 MB de la 5.4.0. La diferencia se debe a que la 5.5.1 eliminó buildx como dependencia de Go.
Para que las descargas fueran reales sin tocar las imágenes de otros proyectos de la máquina, copié los índices originales de Docker Hub a un registro privado de imágenes Docker local con registry:3. La copia con docker buildx imagetools create conserva el digest del índice byte a byte. El proyecto, llamado b4p4-s1, tiene tres servicios: nginx 1.29, Redis 7.2 y PostgreSQL 17, los tres sobre Alpine. Primero lo creé con la 5.4.0 y después pasé a la 5.5.1:
../docker-compose-5.4.0 -p b4p4-s1 up -d --quiet-pull
docker ps -a -f label=com.docker.compose.project=b4p4-s1 \
--format '{{.Names}} {{.Label "com.docker.compose.image"}}' \
| sort | cut -c1-40
../docker-compose-5.5.1 -p b4p4-s1 up -d
La consulta de etiquetas muestra el cambio de digest. Con la 5.4.0 y las imágenes recién descargadas, cada contenedor guarda el digest del índice:
b4p4-s1-cache-1 sha256:ccd6aa8d45ff3f033
b4p4-s1-db-1 sha256:18cfe3ef5e6815560c98
b4p4-s1-web-1 sha256:42a516af16b852e33b7
Tras el primer up con la 5.5.1, la misma consulta devuelve el digest del manifiesto arm64 de cada imagen:
b4p4-s1-cache-1 sha256:efd8e95c7f61fcb75
b4p4-s1-db-1 sha256:dfc2780980fe6ca2d158
b4p4-s1-web-1 sha256:77d740efa8f9c4753f2
El up de la 5.5.1 imprimió Recreate y Recreated para los tres contenedores, y el siguiente up solo Running. Repetí la secuencia con la 5.5.0 en el Docker-in-Docker con containerd y el resultado fue el mismo. No probé Docker Desktop, los volúmenes type: image ni los servicios con platform: fijado, que el pull request también toca.
Cómo saber qué contenedores se van a recrear
La forma directa es preguntar a la versión nueva antes del primer up real. La opción global --dry-run sirve para eso: la referencia de la orden docker compose[5] la presenta como la forma de probar una orden "without changing your application stack state". Lánzala en la carpeta de cada proyecto:
docker compose up -d --dry-run
Cada contenedor afectado aparece con Recreate, y los que se quedan aparecen con Running. Acertó en los cinco escenarios de la tabla. Si instalas Compose desde el repositorio APT de Docker[6], apt upgrade ya trae docker-compose-plugin 5.5.1, así que el momento de mirar es justo después de actualizar el paquete. Si prefieres elegir tú ese momento, retén el paquete con sudo apt-mark hold docker-compose-plugin.
Si tienes más de un proyecto o aún no has actualizado, puedes calcularlo con el cliente de Docker. Este guion compara la etiqueta de cada contenedor con el digest del manifiesto de tu plataforma, que es lo que escribirá la 5.5:
proj=mi_proyecto
plat=$(docker version -f '{{.Server.Os}}/{{.Server.Arch}}')
f='{{index .Config.Labels "com.docker.compose.image"}}'
for c in $(docker ps -q -f "label=com.docker.compose.project=$proj"); do
img=$(docker inspect -f '{{.Config.Image}}' "$c")
lab=$(docker inspect -f "$f" "$c")
new=$(docker image inspect --platform "$plat" -f '{{.Id}}' "$img")
[ "$lab" = "$new" ] && echo "se queda $img" || echo "se recrea $img"
done
Lo probé contra los tres motores y dio el mismo veredicto que --dry-run: se recrea para lo creado por v2.40.3 en containerd y se queda en overlay2. Necesita un cliente de Docker con image inspect --platform; el mío era el 29.5.2. En cambio, docker compose config --hash no te sirve aquí. Ese comando devuelve el hash de la configuración del servicio, y la etiqueta com.docker.compose.config-hash de mis contenedores era idéntica antes y después de la recreación.
Cuánto dura la recreación y cómo elegir el momento
La recreación para, borra y vuelve a crear cada servicio, así que el corte depende de lo que tarde tu aplicación en parar y arrancar. Repetí tres veces el paso de 5.4.0 a 5.5.1 con PostgreSQL ya listo y una sonda HTTP contra nginx cada 50 ms:
| Medida | Ejecución 1 | Ejecución 2 | Ejecución 3 | Mediana |
|---|---|---|---|---|
up -d completo |
2,50 s | 2,34 s | 2,01 s | 2,34 s |
| nginx sin responder | 1,32 s | 1,27 s | 1,35 s | 1,32 s |
| Redis, de la parada al arranque | 1,48 s | 1,46 s | 1,06 s | 1,46 s |
| PostgreSQL, de la parada al arranque | 0,91 s | 0,99 s | 1,34 s | 0,99 s |
La máquina estaba compartida con otras cargas: la media de un minuto iba de 24,9 a 26,4 con 18 núcleos, así que tómalo como orden de magnitud. En un primer intento, PostgreSQL aún estaba inicializando la base de datos, no atendió la señal de parada y Docker lo mató tras los 10 s que da stop_grace_period por defecto. Ese up tardó 17,47 s.
Según la referencia de docker compose up[7], la recreación conserva los volúmenes montados. Lo que se pierde es lo escrito solo en la capa del contenedor, como explica la guía de volúmenes y bind mounts en Docker.
Para que el corte llegue cuando tú quieras, sigue este orden:
- Ejecuta
docker compose up -d --dry-runcon la versión nueva en cada proyecto. - Si no es buen momento, usa
docker compose up -d --no-recreate. Arranca lo que falte sin recrear nada, pero la recreación queda pendiente: comprobé que el siguienteupsin la opción la hace. - Para servicios que tardan en parar o en estar listos, revisa
stop_grace_periody los healthchecks y políticas de reinicio en Docker Compose antes de lanzar elupdefinitivo.
Qué hace pull_policy con daily, weekly y every_N
Con pull_policy: daily, weekly o every_<duración>, docker compose up solo consulta el registro si la última descarga de la imagen supera la ventana. Así lo documenta la referencia de servicios del fichero Compose[8]. Compose lee esa fecha del campo LastTagTime de la imagen, y en Docker 29.5.2 una descarga sin cambios también lo actualiza, así que la ventana se reinicia en cada consulta. Lo comprobé con una ventana de dos minutos:
services:
web:
image: localhost:21401/b4p4/web:stable
pull_policy: every_2m
ports:
- "127.0.0.1:21411:80"
Con la 5.5.1, arranqué con nginx 1.29.0, moví la etiqueta del registro a 1.29.1 y lancé up otra vez. Dentro de la ventana no descargó nada y nginx siguió respondiendo Server: nginx/1.29.0. Pasados los dos minutos, el mismo up descargó la imagen y recreó el contenedor en 9,43 s en total, y la respuesta pasó a Server: nginx/1.29.1.
La nota de la versión 5.5.0 añade que "compose pull now honors pull_policy refresh windows (daily, weekly, every_N)". En mis pruebas no fue así.
Un docker compose pull explícito descargó la imagen dentro de la ventana con la 5.4.0, la 5.5.0 y la 5.5.1. El pull request #14041 de Docker Compose[9], incluido en la 5.5.0, lo explica: un pull explícito trata la ventana como vencida, porque es la única forma de forzar una descarga antes de tiempo. Si quieres que la ventana mande, usa up.
El cambio que sí notarás está en los ciclos de descarga. Con containerd, la 5.4.0 recreaba el contenedor sin que la imagen cambiara; la 5.5.1, no. Esto es lo que pasó con pull_policy: every_1m y la misma imagen todo el rato:
| Paso | Compose 5.4.0 | Compose 5.5.1 |
|---|---|---|
up 1, con descarga |
Crea | Crea |
up 2, dentro de la ventana |
Recrea | Sigue igual |
up 3, ventana vencida y descarga |
Recrea | Sigue igual |
up 4, dentro de la ventana |
Recrea | Sigue igual |
Esto convierte a up con ventana en un sustituto razonable de Watchtower para actualizar contenedores, cuyo repositorio original se archivó el 17 de diciembre de 2025. Programa docker compose up -d cada hora con cron o con un temporizador de systemd y cada imagen se consultará como mucho una vez al día. No lo he probado como tarea programada en esta máquina, solo el comportamiento de up. Tampoco tendrás notificaciones, limpieza de imágenes antiguas ni exclusión por etiquetas, que sí ofrece el fork mantenido de Watchtower.
Preguntas frecuentes
¿Puedo evitar la recreación sin quedarme en Compose 5.4?
No, solo aplazarla. docker compose up -d --no-recreate deja los contenedores como están, pero la etiqueta conserva el digest antiguo y el siguiente up normal los recrea. Hazlo una vez, en una ventana de mantenimiento, y los up siguientes ya no recrean nada.
¿Pierdo datos cuando Compose recrea un contenedor?
No pierdes lo que esté en volúmenes o montajes, porque Compose los conserva al recrear. Pierdes lo escrito en la capa del contenedor fuera de ellos, igual que en cualquier otra recreación.
¿Por qué no se recrean mis contenedores después de actualizar?
Porque usas overlay2, porque tus servicios construyen la imagen con build: o porque la 5.4 ya los recreó en un segundo up. En los tres casos la etiqueta ya coincide con lo que calcula la 5.5.
Conclusión
La recreación de Compose 5.5 es un pago único. Corrige una comparación de digests que en containerd daba cambios falsos y, a cambio, recrea una vez lo que se creó con la lógica anterior. Antes del primer up, ejecuta docker compose up -d --dry-run con la versión nueva en cada proyecto y decide cuándo parar los servicios afectados. Si usas pull_policy con ventanas, la 5.5 deja de recrear en cada ciclo, y esa es la mejora que más se nota en un servidor casero.
Fuentes
- notas de la versión 5.5.0 de Docker Compose
- pull request #14011 de Docker Compose
- documentación de Docker sobre el almacén de containerd
- versión 5.5.1 de Docker Compose
- referencia de la orden docker compose
- repositorio APT de Docker
- referencia de docker compose up
- referencia de servicios del fichero Compose
- pull request #14041 de Docker Compose
- containrrr/watchtower, repositorio archivado
Código fuente
Accede a todo el código fuente de este artículo en GitHub.
Ver en GitHub