Registrarás el digest activo, descargarás una imagen nueva sin aplicarla, validarás Compose, recrearás únicamente el servicio afectado y restaurarás la referencia anterior si falla la puerta de salud.


Por qué actualizar por digest

Una etiqueta como app:stable puede apuntar hoy a una imagen y mañana a otra. Una referencia repositorio@sha256:..., en cambio, identifica contenido inmutable.

Esto mejora la reproducibilidad y la auditoría, pero no demuestra por sí solo que la imagen sea segura o compatible.

Este procedimiento está pensado para Docker Engine y Docker Compose v2 en un único host. Compose no proporciona el rollback automático de un orquestador y, con una sola réplica, puede producirse una interrupción durante la recreación.

Requisitos previos

  • Docker Engine, Docker Compose v2 y Docker Buildx.
  • Acceso al registro y permisos para utilizar Docker.
  • Nombre exacto del servicio Compose.
  • Servicio actual ya fijado mediante repositorio@sha256:....
  • Digest nuevo aprobado para la arquitectura del host.
  • Healthcheck y prueba funcional representativa.
  • Backup y restauración ensayada para los datos persistentes.
  • Espacio para conservar las imágenes anterior y nueva.

No continúes si la actualización ejecuta una migración irreversible. Volver a la imagen anterior no revierte bases de datos, volúmenes ni efectos externos.

Paso 1: registrar el estado actual

Ejecuta estas comprobaciones desde el directorio del proyecto:

docker version
docker compose version
docker info --format '{{.OSType}}/{{.Architecture}}'

cd /ruta/al/proyecto
docker compose config -q
docker compose config --services
docker compose ps

Obtén y valida la referencia exacta del servicio:

CID=$(docker compose ps -q web)
test -n "$CID"

OLD_IMAGE=$(docker inspect --format '{{.Config.Image}}' "$CID")
IMAGE_ID=$(docker inspect --format '{{.Image}}' "$CID")

case "$OLD_IMAGE" in
  *@sha256:*) ;;
  *)
    echo "ERROR: el servicio A no está fijado por digest: $OLD_IMAGE" >&2
    exit 1
    ;;
esac

docker image inspect "$OLD_IMAGE" \
  --format 'id={{.Id}} repo_digests={{json .RepoDigests}}'

printf 'old_image=%s image_id=%s\n' "$OLD_IMAGE" "$IMAGE_ID"

Si el servicio utiliza una etiqueta, detén el procedimiento. Este runbook exige que la versión A ya sea inmutable.

Paso 2: configurar el servicio

services:
  web:
    image: nginx@sha256:DIGEST_ACTIVO
    ports:
      - "127.0.0.1:8080:80"
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O- http://127.0.0.1/ >/dev/null || exit 1"]
      interval: 10s
      timeout: 3s
      retries: 6
      start_period: 10s

En este ejemplo, el digest debe haberse aprobado a partir de nginx:alpine, ya que el healthcheck depende de wget. La referencia desplegada omite la etiqueta porque el digest es quien determina el contenido.

Paso 3: verificar el digest nuevo

docker buildx version
docker buildx imagetools inspect nginx:alpine

IMAGE_REPO=nginx
NEW_DIGEST=sha256:DIGEST_NUEVO
NEW_IMAGE="$IMAGE_REPO@$NEW_DIGEST"

docker pull "$NEW_IMAGE"

docker image inspect "$NEW_IMAGE" \
  --format 'repo_digests={{json .RepoDigests}} image_id={{.Id}} os={{.Os}} arch={{.Architecture}}'

Comprueba que el sistema operativo y la arquitectura coincidan con el host. En imágenes multi-plataforma, documenta si aprobaste el digest del índice o el manifiesto específico.

Paso 4: validar sin aplicar

cp compose.yaml compose.rollback.yaml
cp compose.yaml compose.next.yaml
chmod 600 compose.rollback.yaml compose.next.yaml

# Reemplaza únicamente el digest en compose.next.yaml.
docker compose -f compose.next.yaml config -q
docker compose -f compose.next.yaml config --images
docker compose -f compose.next.yaml pull web

config --images debe mostrar el digest nuevo. pull descarga la imagen sin iniciar contenedores. Si alguna comprobación falla, no reemplaces el archivo activo.

Este ejemplo presupone un único compose.yaml. Si utilizas varios archivos -f, COMPOSE_FILE, perfiles, .env o variables externas, registra y reutiliza el mismo conjunto tanto en la actualización como en el rollback.

Paso 5: actualizar únicamente el servicio

mv compose.next.yaml compose.yaml

docker compose up -d \
  --wait \
  --wait-timeout 90 \
  --no-deps \
  web

Compose recreará el contenedor al detectar el cambio de imagen y conservará los volúmenes montados. --no-deps debe utilizarse solamente cuando las dependencias no necesiten reiniciarse.

Paso 6: comprobar el resultado

docker compose ps web
docker compose logs --tail=100 web
curl -fsS http://127.0.0.1:8080/

CID=$(docker compose ps -q web)
test -n "$CID"

docker inspect --format \
  'ref={{.Config.Image}} image_id={{.Image}} health={{if .State.Health}}{{.State.Health.Status}}{{else}}sin-healthcheck{{end}}' \
  "$CID"

Acepta la actualización únicamente cuando:

  • el servicio esté running/healthy;
  • la prueba funcional responda correctamente;
  • los logs no contengan errores nuevos;
  • Config.Image coincida con el digest nuevo;
  • no se hayan recreado servicios ajenos al cambio.

No uses || true para ocultar errores de validación, descarga, salud o conectividad.

Cómo volver al digest anterior

cp compose.rollback.yaml compose.yaml

docker compose config -q
docker compose config --images

OLD_IMAGE=nginx@sha256:DIGEST_ANTERIOR
docker image inspect "$OLD_IMAGE"

docker compose up -d \
  --wait \
  --wait-timeout 90 \
  --pull never \
  --no-deps \
  web

Reemplaza DIGEST_ANTERIOR por el valor registrado en el Paso 1. --pull never obliga a utilizar la copia local de A y evita que la recuperación dependa del registro.

El rollback termina cuando Config.Image vuelve a OLD_IMAGE, el healthcheck pasa y la prueba funcional responde correctamente. Docker documenta que compose up recrea servicios cuando cambia la imagen, que --wait espera el estado saludable y que --pull never evita descargas. Docker Compose: up

Qué no revierte este rollback

  • Migraciones o cambios de esquema.
  • Archivos modificados en volúmenes o bind mounts.
  • Mensajes, trabajos o llamadas externas ya ejecutadas.
  • Datos de la capa efímera de un contenedor eliminado.

Si existen datos incompatibles, utiliza el procedimiento de restauración ensayado o un forward fix.

Por qué docker compose down no es rollback

docker compose down detiene y elimina contenedores y redes; no restaura una configuración anterior. Con --volumes también puede eliminar volúmenes. Docker Compose: down

Problemas frecuentes

El digest es incompatible: compara docker info con las plataformas del índice.

Compose conserva la imagen anterior: revisa config --images, el archivo efectivo y Config.Image. No uses --no-recreate.

El contenedor está running pero no healthy: revisa el healthcheck, el endpoint, los logs y las dependencias.

El rollback no recupera el servicio: busca incompatibilidades en datos, configuración, secretos o sistemas externos. No elimines volúmenes para forzar el arranque.

Conclusión

La actualización es recuperable solamente si registras el digest anterior, conservas la imagen local, validas antes de aplicar y repites las pruebas después de restaurar. Revertir una imagen y restaurar datos son operaciones diferentes.

Cloud Serversby Donweb

Todo el poder de la nube a tus proyectos y aplicaciones.
Alojamiento ultra rápido, escalable y con alta disponibilidad.

  • Performance que te sorprenderá
  • Rápida escalabilidad y sin limitaciones
  • Arquitectura de alta disponibilidad
  • Soporte experto y ejecutivos de cuenta
  • Pagos en tu moneda y facturación local

Descubre la mejor solución de Cloud Hosting