Publicación
Publicar imágenes Docker en un registro (registry) es un paso esencial para compartir y distribuir las imágenes de contenedor construidas durante el desarrollo.
En este proyecto se utiliza la siguiente herramienta:
Crane
Crane es una herramienta que facilita la manipulación y gestión de imágenes Docker en registros remotos. Está diseñada para trabajar con registros alternativos al registro predeterminado de Docker, como Amazon ECR, Google Container Registry, Azure Container Registry, entre otros.
Funcionalidades clave de Crane:
- Interfaz simplificada: Ofrece una interfaz de línea de comandos sencilla para gestionar imágenes en registros distintos al predeterminado de Docker.
- Soporte para registros alternativos: Permite trabajar con una variedad de registros, lo que resulta útil para proyectos que no utilizan Docker Hub como repositorio principal.
- Autenticación y manejo de credenciales: Facilita la autenticación y gestión de credenciales para interactuar con registros remotos, permitiendo autenticarse fácilmente para acceder y manipular imágenes.
- Push y pull de imágenes: Permite enviar (push) y recuperar (pull) imágenes desde y hacia registros remotos, de manera similar al funcionamiento con el registro predeterminado de Docker.
- Gestión de etiquetas y versiones: Ofrece opciones para gestionar etiquetas y versiones de imágenes, facilitando la identificación y manipulación de versiones específicas.
Ventajas de utilizar Crane:
- Facilita la migración: Simplifica el proceso de migración entre diferentes registros de imágenes al proporcionar una herramienta dedicada para la manipulación de imágenes.
- Flexibilidad en la elección del registro: Permite utilizar registros alternativos a Docker Hub según las necesidades de la infraestructura y las políticas de seguridad.
- Automatización en flujos de trabajo: Puede integrarse fácilmente en flujos de trabajo automatizados y scripts de CI/CD, al ser compatible con diversos registros.
Uso de Crane:
- Instalación: Crane se puede instalar como una herramienta independiente y utilizarse desde la línea de comandos.
- Comandos básicos: Ofrece comandos como
crane pull
,crane push
,crane auth
, entre otros, análogos a los comandos de Docker pero adaptados para registros remotos. - Configuración de credenciales: Antes de interactuar con registros remotos, es necesario configurar las credenciales correspondientes para la autenticación.
Limitaciones:
Aunque Crane es útil para trabajar con registros alternativos, puede tener algunas limitaciones en comparación con las funcionalidades específicas que ofrecen las herramientas nativas de cada registro.
Uso
GitLab
El primer paso es registrar las credenciales del registro de contenedores en las variables de CI/CD de GitLab. Para ello, en Harbor se crea una cuenta de robot, que puede ser global o por proyecto.
Una vez preparado el usuario, se puede publicar la imagen generada previamente en el job docker_build
mediante el siguiente job de ejemplo:
docker_push:
stage: push_image
dependencies: ["docker_build"]
variables:
GIT_STRATEGY: none
image:
name: gcr.io/go-containerregistry/crane:v0.16.1
entrypoint: [""]
script:
- cd tar_images
- |
crane auth login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASS $DOCKER_REGISTRY_URL;
for tar_image in *.tar;
do
crane push $tar_image $DOCKER_REGISTRY_URL/osdo/osdo-app:$CI_COMMIT_SHORT_SHA -v;
DIGEST=$(crane digest $DOCKER_REGISTRY_URL/osdo/osdo-app:$CI_COMMIT_SHORT_SHA);
echo "DIGEST=${DIGEST}" >> digest.env
done
artifacts:
reports:
dotenv: tar_images/digest.env
expire_in: 10 min
El job docker_push
se encuentra en la etapa push_image
del pipeline de CI/CD y se encarga de publicar las imágenes Docker construidas previamente en el job docker_build
.
- dependencies: ["docker_build"]: Este job depende del resultado exitoso del job
docker_build
, asegurando que las imágenes a publicar estén construidas correctamente. - variables:
GIT_STRATEGY: none
indica que no se requiere ninguna estrategia específica de Git para este job, ya que se trata principalmente de operaciones sobre contenedores. - image: Utiliza la imagen oficial de Crane para ejecutar las operaciones de publicación.
- script:
- Autentica con el registro de contenedores utilizando las credenciales proporcionadas en las variables de entorno.
- Cambia al directorio
tar_images
, donde se encuentran las imágenes Docker en formato.tar
. - Itera sobre cada archivo
.tar
y utiliza Crane para publicar la imagen en el registro, etiquetándola con el valor de$CI_COMMIT_SHORT_SHA
. - Obtiene el digest de la imagen publicada y lo almacena en un archivo
digest.env
.
- artifacts: Se configura para almacenar el archivo
digest.env
como artefacto, lo que permite registrar el digest de la imagen publicada y utilizarlo en etapas posteriores, por ejemplo, para firmar la imagen.
GitHub
docker_push:
name: docker_push
needs: docker_build
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v5
with:
go-version: '1.24'
- name: Checkout code
uses: actions/checkout@v2
- name: Install Crane
- uses: imjasonh/setup-crane@v0.1
- name: Load Docker image
run: |
mkdir -p tar_images
tar -xf tar_images/osdo-app.tar -C tar_images
- name: Login to Docker registry
run: |
crane auth login -u ${{ secrets.DOCKER_REGISTRY_USER }} -p ${{ secrets.DOCKER_REGISTRY_PASS }} ${{ secrets.DOCKER_REGISTRY_URL }}
- name: Push Docker image
id: push
run: |
for tar_image in tar_images/*.tar; do
crane push $tar_image ${{ secrets.DOCKER_REGISTRY_URL }}/osdo/osdo-app:${{ github.sha }} -v
DIGEST=$(crane digest ${{ secrets.DOCKER_REGISTRY_URL }}/osdo/osdo-app:${{ github.sha }})
echo "DIGEST=${DIGEST}" >> $GITHUB_OUTPUT
done
output:
digest: ${{ steps.push.outputs.DIGEST }}
El job docker_push
se encarga de publicar las imágenes Docker generadas en el job docker_build
en un registro de contenedores.
- needs: Indica que este job depende del job
docker_build
, asegurando que las imágenes estén listas antes de intentar publicarlas. - runs-on: Especifica que el job se ejecutará en un runner con Ubuntu.
- steps: Define los pasos a seguir en el job:
- Checkout code: Utiliza la acción
actions/checkout@v2
para clonar el repositorio y acceder al código fuente. - Load Docker image: Descomprime las imágenes Docker almacenadas en formato
.tar
dentro del directoriotar_images
. - Login to Docker registry: Utiliza Crane para autenticar con el registro de contenedores, utilizando las credenciales almacenadas en los secretos de GitHub.
- Push Docker image: Itera sobre cada imagen
.tar
, la publica en el registro y obtiene su digest, que se almacena como salida del job.
- Checkout code: Utiliza la acción
- output: Define una salida llamada
digest
que contiene el digest de la imagen publicada, permitiendo su uso en etapas posteriores del workflow.
Jenkins
stage('Push Docker Images') {
environment {
DOCKER_REGISTRY_URL = 'harbor.opensecdevops.com'
}
steps {
// Solo dentro de este bloque estarán disponibles las vars DOCKER_REGISTRY_USER / _PASs
withCredentials([usernamePassword(
credentialsId: 'DOCKER_REGISTRY',
usernameVariable: 'DOCKER_REGISTRY_USER',
passwordVariable: 'DOCKER_REGISTRY_PASS'
)]) {
script {
unstash 'docker-image'
def shortSha = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
sh '''
for tar_image in tar_images/*.tar; do
[ -e "$tar_image" ] || continue
file=$(basename "$tar_image")
# Login
docker run --rm \
-v /workspace/${JOB_NAME}:/workspace \
-w /workspace \
gcr.io/go-containerregistry/crane:latest \
auth login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASS $DOCKER_REGISTRY_URL
# Push con tag por SHA
docker run --rm \
-v /workspace/${JOB_NAME}:/workspace \
-w /workspace \
gcr.io/go-containerregistry/crane:latest \
push "tar_images/$file" $DOCKER_REGISTRY_URL/osdo/osdo-app-jenkins:$shortSha -v
# Obtener digest y volcar en digest.env
DIGEST=$(docker run --rm \
-v /workspace/${JOB_NAME}:/workspace \
-w /workspace \
gcr.io/go-containerregistry/crane:latest \
digest $DOCKER_REGISTRY_URL/osdo/osdo-app-jenkins:$shortSha)
echo "DIGEST=$DIGEST" >> tar_images/digest.env
done
'''
}
}
}
post {
success {
archiveArtifacts artifacts: 'tar_images/digest.env', fingerprint: true
}
}
}
El job Push Docker Images
se encarga de publicar las imágenes Docker generadas en el job anterior en un registro de contenedores.
- environment: Define la variable
DOCKER_REGISTRY_URL
con la URL del registro de contenedores. - steps: Contiene los pasos a seguir en el job:
- withCredentials: Utiliza las credenciales almacenadas en Jenkins para autenticar con el registro de contenedores. Las variables
DOCKER_REGISTRY_USER
yDOCKER_REGISTRY_PASS
estarán disponibles solo dentro de este bloque. - script: Ejecuta un script que realiza las siguientes acciones:
- Descomprime las imágenes Docker almacenadas en formato
.tar
dentro del directoriotar_images
. - Obtiene el SHA corto del commit actual para etiquetar las imágenes.
- Itera sobre cada imagen
.tar
, autenticándose en el registro y publicando la imagen con la etiqueta correspondiente al SHA. - Obtiene el digest de la imagen publicada y lo almacena en un archivo
digest.env
.
- Descomprime las imágenes Docker almacenadas en formato
- withCredentials: Utiliza las credenciales almacenadas en Jenkins para autenticar con el registro de contenedores. Las variables
- post: Define acciones a realizar después de la ejecución del job:
- success: Si el job se ejecuta correctamente, archiva el archivo
digest.env
como artefacto, permitiendo su uso en etapas posteriores del pipeline.
- success: Si el job se ejecuta correctamente, archiva el archivo
- fingerprint: Habilita el fingerprinting del archivo
digest.env
, lo que permite rastrear su uso y cambios a lo largo del tiempo.