Migración masiva de imágenes
Esta guía te muestra cómo migrar imágenes de Docker de forma masiva entre organizaciones o espacios de nombres de Docker Hub. Tanto si estás consolidando repositorios, cambiando la estructura de la organización o moviendo imágenes a una nueva cuenta, estas técnicas te ayudan a migrar de manera eficiente mientras preservas la integridad de las imágenes.
Este tema está estructurado para aumentar de escala:
- Migrar la etiqueta de una sola imagen
- Migrar todas las etiquetas de un repositorio
- Migrar múltiples repositorios
La herramienta recomendada para este flujo de trabajo es crane. También se muestra una alternativa equivalente que utiliza regctl. Ambas herramientas realizan copias directamente de registro a registro sin descargar las imágenes localmente y preservan las imágenes multiarquitectura.
Se recomienda crane por su simplicidad y su flujo de trabajo centrado en la copia de imágenes. regctl también es una buena opción, especialmente si ya la utilizas para tareas de gestión de registros más amplias más allá de la copia de imágenes.
NoteLos flujos de trabajo principales de este tema operan únicamente con imágenes etiquetadas. Los manifiestos sin etiqueta o el contenido al que ya no se pueda acceder mediante etiquetas no se migran. En la práctica, suelen ser artefactos no utilizados, pero ten en cuenta esta limitación antes de la migración. Aunque puedes migrar manifiestos específicos sin etiqueta utilizando referencias de resumen (digest), no existe ninguna API para enumerar los manifiestos sin etiqueta en un repositorio.
Requisitos previos
Antes de comenzar, asegúrate de tener:
- Una de las siguientes herramientas instalada y disponible en tu
$PATH: - Acceso de escritura (push) tanto en la organización de origen como en la de destino
- Autenticación del registro configurada para la herramienta elegida
Autenticarse en los registros
Ambas herramientas se autentican directamente contra los registros:
craneutiliza los asistentes de credenciales de Docker y~/.docker/config.json. Consulta la documentación de crane.regctlutiliza su propio archivo de configuración y puede importar credenciales de Docker. Consulta la documentación de regctl.
Sigue las instrucciones de autenticación para el registro y la herramienta que prefieras.
Migrar la etiqueta de una sola imagen
Este es el escenario de migración más simple y común.
El siguiente script de ejemplo copia el manifiesto de la imagen directamente entre registros y preserva las imágenes multiarquitectura cuando están presentes. Repite este proceso para cada etiqueta que quieras migrar. Reemplaza los valores de las variables de entorno con los nombres de tus organizaciones de origen y destino, el nombre del repositorio y la etiqueta.
#!/usr/bin/env bash
set -euo pipefail
SRC_ORG="oldorg"
DEST_ORG="neworg"
REPO="myapp"
TAG="1.2.3"
SRC_IMAGE="${SRC_ORG}/${REPO}:${TAG}"
DEST_IMAGE="${DEST_ORG}/${REPO}:${TAG}"
# Usando crane (recomendado)
crane cp "${SRC_IMAGE}" "${DEST_IMAGE}"
# Usando regctl (alternativa)
# regctl image copy "${SRC_IMAGE}" "${DEST_IMAGE}"Migrar por resumen (digest)
Para migrar una imagen específica por su resumen en lugar de por su etiqueta, usa el resumen en la referencia de origen. Esto es útil cuando necesitas migrar una versión exacta de la imagen, incluso si la etiqueta se ha actualizado. Reemplaza los valores de las variables de entorno con los nombres de tus organizaciones de origen y destino, el nombre del repositorio, el resumen y la etiqueta. Puedes elegir entre crane y regctl para la operación de copia.
#!/usr/bin/env bash
set -euo pipefail
SRC_ORG="oldorg"
DEST_ORG="neworg"
REPO="myapp"
DIGEST="sha256:abcd1234..."
TAG="stable"
SRC_IMAGE="${SRC_ORG}/${REPO}@${DIGEST}"
DEST_IMAGE="${DEST_ORG}/${REPO}:${TAG}"
# Usando crane
crane cp "${SRC_IMAGE}" "${DEST_IMAGE}"
# Usando regctl
# regctl image copy "${SRC_IMAGE}" "${DEST_IMAGE}"Migrar todas las etiquetas de un repositorio
Para migrar cada imagen etiquetada en un repositorio, usa la API de Docker Hub para enumerar las etiquetas y copiar cada una. El siguiente script de ejemplo recupera todas las etiquetas de un repositorio determinado y las migra en un bucle. Este enfoque se escala a repositorios con muchas etiquetas sin sobrecargar los recursos locales. Ten en cuenta que existe un límite de frecuencia en las solicitudes a Docker Hub, por lo que es posible que debas añadir retrasos o gestionar la paginación en repositorios grandes.
Reemplaza los valores de las variables de entorno con los nombres de tus organizaciones de origen y destino y el nombre del repositorio. Si tu repositorio de origen es privado, configura también HUB_USER y HUB_TOKEN con credenciales que tengan acceso de lectura (pull). También puedes elegir entre crane y regctl para la operación de copia.
#!/usr/bin/env bash
set -euo pipefail
# Usa variables de entorno si están configuradas; de lo contrario, usa valores por defecto
SRC_ORG="${SRC_ORG:-oldorg}"
DEST_ORG="${DEST_ORG:-neworg}"
REPO="${REPO:-myapp}"
# Opcional: para repositorios privados
# HUB_USER="your-username"
# HUB_TOKEN="your-access-token"
# AUTH="-u ${HUB_USER}:${HUB_TOKEN}"
AUTH=""
TOOL="crane" # o: TOOL="regctl"
TAGS_URL="https://hub.docker.com/v2/repositories/${SRC_ORG}/${REPO}/tags?page_size=100"
while [[ -n "${TAGS_URL}" && "${TAGS_URL}" != "null" ]]; do
RESP=$(curl -fsSL ${AUTH} "${TAGS_URL}")
echo "${RESP}" | jq -r '.results[].name' | while read -r TAG; do
[[ -z "${TAG}" ]] && continue
SRC_IMAGE="${SRC_ORG}/${REPO}:${TAG}"
DEST_IMAGE="${DEST_ORG}/${REPO}:${TAG}"
echo "Migrando ${SRC_IMAGE} → ${DEST_IMAGE}"
case "${TOOL}" in
crane)
crane cp "${SRC_IMAGE}" "${DEST_IMAGE}"
;;
regctl)
regctl image copy "${SRC_IMAGE}" "${DEST_IMAGE}"
;;
esac
done
TAGS_URL=$(echo "${RESP}" | jq -r '.next')
doneNoteDocker Hub crea automáticamente el repositorio de destino en la primera subida si tu cuenta tiene los permisos necesarios.
Migrar múltiples repositorios
Para migrar varios repositorios, crea una lista y ejecuta el script de repositorio único para cada uno.
Por ejemplo, crea un archivo repos.txt con los nombres de los repositorios:
api
web
workerGuarda el script de la sección anterior como migrate-single-repo.sh. Luego, ejecuta el siguiente script de ejemplo que procesa cada repositorio del archivo. Reemplaza los valores de las variables de entorno con los nombres de tus organizaciones de origen y destino.
#!/usr/bin/env bash
set -euo pipefail
SRC_ORG="oldorg"
DEST_ORG="neworg"
while read -r REPO; do
[[ -z "${REPO}" ]] && continue
echo "==== Migrando repo: ${REPO}"
SRC_ORG="${SRC_ORG}" DEST_ORG="${DEST_ORG}" REPO="${REPO}" ./migrate-single-repo.sh
done < repos.txtVerificar la integridad de la migración
Después de copiar, verifica que el origen y el destino coincidan comparando sus resúmenes (digests).
Verificación básica del resumen
El siguiente script de ejemplo recupera el resumen de la imagen para una etiqueta específica tanto del origen como del destino y los compara. Si los resúmenes coinciden, la migración se ha realizado correctamente. Reemplaza los valores de las variables de entorno con los nombres de tus organizaciones de origen y destino, el nombre del repositorio y la etiqueta. Puedes elegir entre crane y regctl para obtener los resúmenes.
#!/usr/bin/env bash
set -euo pipefail
SRC_ORG="oldorg"
DEST_ORG="neworg"
REPO="myapp"
TAG="1.2.3"
SRC_IMAGE="${SRC_ORG}/${REPO}:${TAG}"
DEST_IMAGE="${DEST_ORG}/${REPO}:${TAG}"
# Usando crane
SRC_DIGEST=$(crane digest "${SRC_IMAGE}")
DEST_DIGEST=$(crane digest "${DEST_IMAGE}")
# Usando regctl (alternativa)
# SRC_DIGEST=$(regctl image digest "${SRC_IMAGE}")
# DEST_DIGEST=$(regctl image digest "${DEST_IMAGE}")
echo "Origen: ${SRC_DIGEST}"
echo "Destino: ${DEST_DIGEST}"
if [[ "${SRC_DIGEST}" == "${DEST_DIGEST}" ]]; then
echo "✓ Migración verificada: los resúmenes coinciden"
else
echo "✗ Error en la migración: los resúmenes no coinciden"
exit 1
fiVerificación de multiarquitectura
Para imágenes multiarquitectura, verifica también la lista de manifiestos para asegurarte de que todas las plataformas se copiaron correctamente. Reemplaza los valores de las variables de entorno con los nombres de tus organizaciones de origen y destino, el nombre del repositorio y la etiqueta. Puedes elegir entre crane y regctl para obtener los manifiestos.
#!/usr/bin/env bash
set -euo pipefail
SRC_ORG="oldorg"
DEST_ORG="neworg"
REPO="myapp"
TAG="1.2.3"
SRC_IMAGE="${SRC_ORG}/${REPO}:${TAG}"
DEST_IMAGE="${DEST_ORG}/${REPO}:${TAG}"
# Usando crane
SRC_MANIFEST=$(crane manifest "${SRC_IMAGE}")
DEST_MANIFEST=$(crane manifest "${DEST_IMAGE}")
# Usando regctl (alternativa)
# SRC_MANIFEST=$(regctl image manifest --format raw-body "${SRC_IMAGE}")
# DEST_MANIFEST=$(regctl image manifest --format raw-body "${DEST_IMAGE}")
# Comprueba si es una lista de manifiestos (multiarquitectura)
if echo "${SRC_MANIFEST}" | jq -e '.manifests' > /dev/null 2>&1; then
echo "Imagen multiarquitectura detectada"
# Compara la lista de plataformas
SRC_PLATFORMS=$(echo "${SRC_MANIFEST}" | jq -r '.manifests[] | "\(.platform.os)/\(.platform.architecture)"' | sort)
DEST_PLATFORMS=$(echo "${DEST_MANIFEST}" | jq -r '.manifests[] | "\(.platform.os)/\(.platform.architecture)"' | sort)
if [[ "${SRC_PLATFORMS}" == "${DEST_PLATFORMS}" ]]; then
echo "✓ La lista de plataformas coincide:"
echo "${SRC_PLATFORMS}"
else
echo "✗ Las listas de plataformas no coinciden"
echo "Plataformas de origen:"
echo "${SRC_PLATFORMS}"
echo "Plataformas de destino:"
echo "${DEST_PLATFORMS}"
exit 1
fi
else
echo "Imagen de arquitectura única"
fiCompletar la migración
Después de migrar tus imágenes, completa estos pasos adicionales:
Copia los metadatos del repositorio en la interfaz de usuario de Docker Hub o a través de la API:
- Contenido del README
- Descripción del repositorio
- Temas (topics) y etiquetas
Configura los ajustes del repositorio para que coincidan con el origen:
- Visibilidad (pública o privada)
- Permisos de equipo y controles de acceso
Reconfigura las integraciones en la organización de destino:
- Webhooks
- Compilaciones automatizadas
- Escáneres de seguridad
Actualiza las referencias de imágenes en tus proyectos:
- Cambia
FROM oldorg/repo:tagporFROM neworg/repo:tagen tus Dockerfiles - Actualiza las configuraciones de despliegue
- Actualiza la documentación
- Cambia
Declara obsoleta la ubicación antigua:
- Actualiza la descripción del repositorio de origen para que apunte a la nueva ubicación
- Considera añadir un período de gracia antes de hacer que el repositorio antiguo sea privado o de solo lectura