Identificación automática de las imágenes de contenedor duplicadas al migrar a un repositorio de Amazon ECR
Rishabh Yadav y Rishi Singla, Amazon Web Services
Resumen
Aviso: AWS CodeCommit ya no está disponible para los nuevos clientes. Los clientes existentes de AWS CodeCommit pueden seguir utilizando el servicio con normalidad. Más información
El patrón proporciona una solución automatizada para identificar si las imágenes almacenadas en diferentes repositorios de contenedores son duplicadas. Esta comprobación resulta útil si planea migrar imágenes de otros repositorios de contenedor a Amazon Elastic Container Registry (Amazon ECR).
Para obtener información básica, el patrón también describe los componentes de una imagen de contenedor, como el resumen de la imagen, el manifiesto y las etiquetas. Cuando planifique una migración a Amazon ECR, puede decidir sincronizar las imágenes de los contenedores entre los registros de contenedores comparando los resúmenes de las imágenes. Antes de migrar las imágenes de contenedor, debe comprobar si estas imágenes ya existen en el repositorio de Amazon ECR para evitar la duplicación. Sin embargo, puede resultar difícil detectar la duplicación comparando los resúmenes de imágenes, y esto podría provocar problemas en la fase inicial de migración. Este patrón compara los resúmenes de dos imágenes similares que están almacenadas en diferentes registros de contenedores y explica por qué varían los resúmenes con el fin de ayudarle a comparar las imágenes con precisión.
Requisitos previos y limitaciones
Una Cuenta de AWS activa
Acceso al registro público de Amazon ECR
Conocimiento de lo siguiente Servicios de AWS:
Credenciales de CodeCommit configuradas (consulte las instrucciones)
Arquitectura
Componentes de la imagen de contenedor
En el siguiente diagrama se ilustran algunos de los componentes de una imagen de contenedor. Estos componentes se describen después del diagrama.

Términos y definiciones
Los siguientes términos se definen en la especificación de imagen de la Open Container Initiative (OCI)
Registro: servicio de almacenamiento y administración de imágenes.
Cliente: herramienta que se comunica con los registros y funciona con imágenes locales.
Inserción: proceso para cargar imágenes a un registro.
Extracción: proceso de descarga de imágenes de un registro.
Blob: formato binario de contenido que almacena un registro y al que se puede acceder mediante un resumen.
Índice: constructo que identifica varios manifiestos de imágenes para distintos tipos de plataformas informáticas (como x86-64 o ARM de 64 bits) o contenido multimedia. Para obtener más información, consulte la especificación del índice de imágenes de OCI
. Manifiesto: documento JSON que define una imagen o un artefacto que se carga a través del punto de conexión del manifiesto. Un manifiesto puede hacer referencia a otros blobs de un repositorio mediante descriptores. Para obtener más información, consulte la especificación del manifiesto de imágenes de OCI
. Capa del sistema de archivos: bibliotecas del sistema y otras dependencias de una imagen.
Configuración: un blob que contiene metadatos de artefactos y al que se hace referencia en el manifiesto. Para obtener más información, consulte la especificación de la configuración de imágenes de OCI
. Objeto o artefacto: elemento de contenido conceptual que se almacena como un blob y se asocia a un manifiesto adjunto con una configuración.
Resumen: identificador único que se crea a partir de un hash criptográfico del contenido de un manifiesto. El resumen de imágenes ayuda a identificar de forma única una imagen de contenedor inmutable. Al extraer una imagen mediante su resumen, descargará siempre la misma imagen en cualquier sistema operativo o arquitectura. Para obtener más información, consulte la especificación de imágenes de OCI
. Etiqueta: un identificador de manifiesto legible para los humanos. En comparación con los resúmenes de imágenes, que son inmutables, las etiquetas son dinámicas. Una etiqueta que apunta a una imagen puede cambiar y pasar de una imagen a otra, aunque el resumen de la imagen subyacente sigue siendo el mismo.
Arquitectura de destino
El siguiente diagrama muestra la arquitectura de alto nivel de la solución proporcionada por este patrón para identificar imágenes de contenedor duplicadas mediante la comparación de las imágenes almacenadas en Amazon ECR y en repositorios privados.

Herramientas
Servicios de AWS
CloudFormation ayuda a configurar los recursos de AWS, aprovisionarlos de manera rápida y coherente y administrarlos durante todo su ciclo de vida en las regiones y Cuentas de AWS.
AWS CodeBuild es un servicio de compilación completamente administrado que le permite compilar código fuente, poner en marcha pruebas unitarias y producir artefactos listos para implementar.
AWS CodeCommit es un servicio de control de versiones que permite almacenar y administrar repositorios de Git de forma privada, sin necesidad de administrar su propio sistema de control de origen.
AWS CodePipeline permite diseñar y configurar rápidamente las diferentes etapas de un proceso de lanzamiento de software y automatizar los pasos necesarios para lanzar los cambios en el software de manera continua.
Amazon Elastic Container Registry (Amazon ECR) es un servicio de registro de imágenes de contenedor administrado que es seguro, escalable y fiable.
Código de
El código de este patrón está disponible en la solución automatizada del repositorio de GitHub para identificar imágenes de contenedor duplicadas entre repositorios
Prácticas recomendadas
Epics
| Tarea | Descripción | Habilidades requeridas |
|---|---|---|
Extraiga una imagen de un repositorio público de Amazon ECR. | Desde el terminal, ejecute el siguiente comando para extraer la imagen
Cuando la imagen se haya trasladado a su máquina local, verá el siguiente resumen de extracción, que representa el índice de la imagen.
| Desarrollador de aplicaciones, DevOps de AWS, administrador de AWS |
Inserte la imagen en un repositorio privado de Amazon ECR |
| Administrador de AWS, DevOps de AWS, desarrollador de aplicaciones |
Extraiga la misma imagen del repositorio privado de Amazon ECR. |
| Desarrollador de aplicaciones, DevOps de AWS, administrador de AWS |
| Tarea | Descripción | Habilidades requeridas |
|---|---|---|
Busque el manifiesto de la imagen almacenada en el repositorio público de Amazon ECR. | Desde el terminal, ejecute el siguiente comando para extraer el manifiesto de la imagen
| Administrador de AWS, DevOps de AWS, desarrollador de aplicaciones |
Busque el manifiesto de la imagen almacenada en el repositorio privado de Amazon ECR. | Desde el terminal, ejecute el siguiente comando para extraer el manifiesto de la imagen
| Desarrollador de aplicaciones, DevOps de AWS, administrador de sistemas AWS |
Compare el resumen extraído por Docker con el resumen del manifiesto de la imagen en el repositorio privado de Amazon ECR. | Otra pregunta es por qué el resumen proporcionado por el comando docker pull difiere del resumen del manifiesto de la imagen El resumen utilizado para docker pull representa el resumen del manifiesto de la imagen, que se almacena en un registro. Este resumen se considera la raíz de una cadena de hash, porque el manifiesto contiene el hash del contenido que se descargará e importará a Docker. El ID de imagen utilizado en Docker se encuentra en este manifiesto como Para confirmar esta información, puede comparar el resultado del comando docker inspect en los repositorios públicos y privados de Amazon ECR:
Los resultados verifican que ambas imágenes tienen el mismo resumen de ID de imagen y resumen de capa. ID: Capas: Además, los resúmenes se basan en los bytes del objeto que se administra localmente (el archivo local es un tar de la capa de imágenes de contenedor) o en el blob que se inserta en el servidor de registro. Sin embargo, al insertar el blob en un registro, el tar se comprime y el resumen se calcula en el archivo tar comprimido. Por lo tanto, la diferencia en el valor del resumen de extracción de docker se debe a la compresión que se aplica a nivel de registro (Amazon ECR privado o público). notaEsta explicación es específica del uso de un cliente Docker. No verá este comportamiento en otros clientes, como nerdctl o Finch, porque no comprimen automáticamente la imagen durante las operaciones de inserción y extracción. | Desarrollador de aplicaciones, DevOps de AWS, administrador de sistemas AWS |
| Tarea | Descripción | Habilidades requeridas |
|---|---|---|
Clonar el repositorio. | Clone el repositorio de GitHub para este patrón en una carpeta local:
| Administrador de AWS, DevOps de AWS |
Configure la canalización de CI/CD. | El repositorio de GitHub incluye un archivo
La canalización se configurará con dos etapas (CodeCommit y CodeBuild, como se muestra en el diagrama de arquitectura) para identificar las imágenes del repositorio privado que también existen en el repositorio público. La canalización está configurada con los siguientes recursos:
| Administrador de AWS, DevOps de AWS |
Rellene el repositorio de CodeCommit. | Para rellenar el repositorio de CodeCommit, lleve a cabo estos pasos:
| Administrador de AWS, DevOps de AWS |
Eliminar recursos. | Para evitar incurrir en cargos en el futuro, elimine los recursos siguiendo estos pasos:
| Administrador de AWS |
Solución de problemas
| Problema | Solución |
|---|---|
Al intentar enviar, extraer o interactuar con un repositorio de CodeCommit desde el terminal o desde la línea de comandos, el sistema le pide que proporcione un nombre de usuario y una contraseña y debe proporcionar las credenciales de Git para el usuario de IAM. | Las siguientes son las causas comunes para esto:
Según el sistema operativo y el entorno local, es posible que tenga que instalar un gestor de credenciales, configurar el gestor de credenciales que se incluye en el sistema operativo o personalizar su entorno local para utilizar el almacenamiento de credenciales. Por ejemplo, si su equipo ejecuta macOS, puede usar la utilidad Keychain Access para almacenar sus credenciales. Si su equipo utiliza Windows, puede utilizar el Administrador de credenciales de Git que se instala en Git para Windows. Para obtener más información, consulte Configuración para usuarios de HTTPS que utilizan credenciales de Git en la documentación de CodeCommit y Almacenamiento de credenciales |
Al insertar una imagen en el repositorio de Amazon ECR, se producen errores HTTP 403 o “no basic auth credentials”. | Es posible que encuentre estos mensajes de error en los comandos docker push o docker pull, incluso si se ha autenticado correctamente en Docker mediante el comando aws ecr get-login-password. Las causas conocidas son:
|
Recursos relacionados
Solución automatizada para identificar imágenes de contenedor duplicadas entre repositorios
(repositorio de GitHub) Imágenes privadas en Amazon ECR (documentación de Amazon ECR)
Recurso AWS::CodePipeline::Pipeline (CloudFormation documentación)
Información adicional
Resultado de la inspección de Docker para una imagen en el repositorio público de Amazon ECR
[ { "Id": "sha256:f7cee5e1af28ad4e147589c474d399b12d9b551ef4c3e11e02d982fce5eebc68", "RepoTags": [ "<account-id>.dkr.ecr.us-east-1.amazonaws.com/test_ecr_repository:latest", "public.ecr.aws/amazonlinux/amazonlinux:2018.03" ], "RepoDigests": [ "<account-id>.dkr.ecr.us-east-1.amazonaws.com/test_ecr_repository@sha256:52db9000073d93b9bdee6a7246a68c35a741aaade05a8f4febba0bf795cdac02", "public.ecr.aws/amazonlinux/amazonlinux@sha256:f972d24199508c52de7ad37a298bda35d8a1bd7df158149b381c03f6c6e363b5" ], "Parent": "", "Comment": "", "Created": "2023-02-23T06:20:11.575053226Z", "Container": "ec7f2fc7d2b6a382384061247ef603e7d647d65f5cd4fa397a3ccbba9278367c", "ContainerConfig": { "Hostname": "ec7f2fc7d2b6", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"/bin/bash\"]" ], "Image": "sha256:c1bced1b5a65681e1e0e52d0a6ad17aaf76606149492ca0bf519a466ecb21e51", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": {} }, "DockerVersion": "20.10.17", "Author": "", "Config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/bash" ], "Image": "sha256:c1bced1b5a65681e1e0e52d0a6ad17aaf76606149492ca0bf519a466ecb21e51", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": null }, "Architecture": "amd64", "Os": "linux", "Size": 167436755, "VirtualSize": 167436755, "GraphDriver": { "Data": { "MergedDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/merged", "UpperDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/diff", "WorkDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/work" }, "Name": "overlay2" }, "RootFS": { "Type": "layers", "Layers": [ "sha256:d5655967c2c4e8d68f8ec7cf753218938669e6c16ac1324303c073c736a2e2a2" ] }, "Metadata": { "LastTagTime": "2023-03-02T10:28:47.142155987Z" } } ]
Resultado de la inspección de Docker para una imagen en el repositorio privado de Amazon ECR
[ { "Id": "sha256:f7cee5e1af28ad4e147589c474d399b12d9b551ef4c3e11e02d982fce5eebc68", "RepoTags": [ "<account-id>.dkr.ecr.us-east-1.amazonaws.com/test_ecr_repository:latest", "public.ecr.aws/amazonlinux/amazonlinux:2018.03" ], "RepoDigests": [ "<account-id>.dkr.ecr.us-east-1.amazonaws.com/test_ecr_repository@sha256:52db9000073d93b9bdee6a7246a68c35a741aaade05a8f4febba0bf795cdac02", "public.ecr.aws/amazonlinux/amazonlinux@sha256:f972d24199508c52de7ad37a298bda35d8a1bd7df158149b381c03f6c6e363b5" ], "Parent": "", "Comment": "", "Created": "2023-02-23T06:20:11.575053226Z", "Container": "ec7f2fc7d2b6a382384061247ef603e7d647d65f5cd4fa397a3ccbba9278367c", "ContainerConfig": { "Hostname": "ec7f2fc7d2b6", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"/bin/bash\"]" ], "Image": "sha256:c1bced1b5a65681e1e0e52d0a6ad17aaf76606149492ca0bf519a466ecb21e51", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": {} }, "DockerVersion": "20.10.17", "Author": "", "Config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/bash" ], "Image": "sha256:c1bced1b5a65681e1e0e52d0a6ad17aaf76606149492ca0bf519a466ecb21e51", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": null }, "Architecture": "amd64", "Os": "linux", "Size": 167436755, "VirtualSize": 167436755, "GraphDriver": { "Data": { "MergedDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/merged", "UpperDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/diff", "WorkDir": "/var/lib/docker/overlay2/c2c2351a82b26cbdf7782507500e5adb5c2b3a2875bdbba79788a4b27cd6a913/work" }, "Name": "overlay2" }, "RootFS": { "Type": "layers", "Layers": [ "sha256:d5655967c2c4e8d68f8ec7cf753218938669e6c16ac1324303c073c736a2e2a2" ] }, "Metadata": { "LastTagTime": "2023-03-02T10:28:47.142155987Z" } } ]