Construcción
La construcción de imágenes en Docker es el proceso de crear una imagen de contenedor que contiene todo lo necesario para ejecutar una aplicación: desde el sistema operativo base hasta las dependencias y configuraciones específicas de la aplicación.
Kaniko
Kaniko es una herramienta diseñada para construir imágenes de contenedores en entornos donde no se dispone de acceso a privilegios de root ni a un demonio de Docker en ejecución. Esto la hace especialmente útil en sistemas de integración continua (CI) y en entornos controlados donde la seguridad y la portabilidad son prioritarias.
Características principales
- Construcción sin privilegios de root: Kaniko permite construir imágenes de contenedor sin requerir acceso de superusuario, lo que reduce la superficie de ataque y mejora la seguridad en entornos restringidos.
- Compatibilidad con Dockerfile: Utiliza el archivo Dockerfile estándar para definir los pasos de construcción, aceptando la misma sintaxis y comandos que Docker, lo que facilita la migración y reutilización de configuraciones existentes.
- Cacheado de capas: Emplea un sistema de cacheado de capas que acelera los tiempos de construcción al reutilizar capas previamente generadas para instrucciones del Dockerfile que no han cambiado.
- Ejecución como contenedor: Kaniko se ejecuta como un contenedor, lo que proporciona aislamiento, portabilidad y facilidad de integración en diferentes plataformas y sistemas de CI/CD.
- Compatibilidad con repositorios privados: Puede autenticarse y acceder a repositorios privados para obtener capas de imágenes base durante el proceso de construcción, facilitando la gestión de imágenes protegidas.
- Soporte multiplataforma: Permite la construcción de imágenes para diferentes arquitecturas, adaptándose a las necesidades de despliegue en distintos entornos.
Beneficios:
- Seguridad mejorada: Al no requerir privilegios elevados ni acceso directo al demonio de Docker, Kaniko reduce los riesgos asociados a la construcción de imágenes en entornos compartidos o automatizados.
- Portabilidad: Facilita la construcción de imágenes en cualquier entorno compatible con contenedores, sin depender de la infraestructura local o de servicios específicos.
- Optimización de recursos: Permite distribuir la carga de trabajo de construcción en diferentes sistemas o agentes de CI, aprovechando los recursos disponibles de manera eficiente.
- Integración sencilla: Se integra fácilmente en pipelines de CI/CD, permitiendo la automatización completa del proceso de construcción y publicación de imágenes.
GitLab
.docker_build:
stage: build
dependencies: ['composer_prod', 'npm']
extends: .dependencies_cache
image:
name: gcr.io/kaniko-project/executor@sha256:e935bfe222bc3ba84797e90a95fcfb1a63e61bcf81275c2cac5edfb0343b2e85
entrypoint: [""]
script:
- mkdir tar_images
- /kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/deployment/php/Dockerfile"
--destination "${DOCKER_REGISTRY_URL}/osdo/osdo-app:${CI_COMMIT_TAG}" --no-push --tar-path tar_images/osdo_app.tar
artifacts:
paths:
- tar_images
when: on_success
- stage: Define la fase del pipeline en la que se ejecuta este job, en este caso
build
, indicando que corresponde al proceso de construcción de la imagen de contenedor. - dependencies: Especifica que este job depende de los jobs
composer_prod
ynpm
, asegurando que las dependencias PHP y JavaScript estén instaladas antes de construir la imagen. - extends: Hereda la configuración de
.dependencies_cache
, lo que permite reutilizar reglas de caché y otras configuraciones comunes definidas previamente en el pipeline. - image: Utiliza una imagen de contenedor específica de Kaniko, identificada por un hash sha256, que contiene las herramientas necesarias para construir imágenes de contenedor de forma segura y reproducible.
- entrypoint: Sobrescribe el punto de entrada por defecto de la imagen, estableciéndolo como vacío para permitir la ejecución personalizada de comandos en el script.
- script: Lista los comandos principales que se ejecutan en el job:
- Crea el directorio
tar_images
para almacenar la imagen generada en formato tar. - Ejecuta Kaniko con los parámetros necesarios:
--context
: Define el directorio raíz del proyecto como contexto de construcción.--dockerfile
: Especifica la ubicación del Dockerfile a utilizar.--destination
: Indica el destino de la imagen en el registro de contenedores, utilizando la URL y el tag del commit.--no-push
: Indica que la imagen no se subirá automáticamente al registro, sino que se almacenará localmente.--tar-path
: Define la ruta donde se guardará la imagen como archivo tar.
- Crea el directorio
- artifacts: Especifica que el directorio
tar_images
debe conservarse como artefacto tras la ejecución del job, permitiendo su descarga o uso en etapas posteriores del pipeline. El artefacto se guarda solo si el job finaliza correctamente (when: on_success
).
GitHub
docker_build:
name: Docker Build
id: docker_build
runs-on: ubuntu-latest
needs: [composer, npm]
steps:
- name: Clonar repositorio
uses: actions/checkout@v4
- name: Recuperar artifacts
uses: actions/download-artifact@v4
- name: Crear directorio tar_images
run: mkdir -p tar_images
- name: Build Docker image with Kaniko
uses: docker://gcr.io/kaniko-project/executor:latest
with:
entrypoint: ""
args: >
--context .
--dockerfile docker/nginx/Dockerfile
--destination harbor.opensecdevops.com/osdo/osdo-app:${{ github.sha }}
--tar-path tar_images/osdo_app.tar
--no-push
- name: Upload Docker image tar
uses: actions/upload-artifact@v4
with:
name: docker_image
path: tar_images/
retention-days: 1
- name: Define el nombre del job como
Docker Build
, facilitando su identificación dentro del workflow de GitHub Actions. - runs-on: Especifica el sistema operativo del runner donde se ejecutará el job, en este caso
ubuntu-latest
, asegurando un entorno limpio y consistente para cada ejecución. - needs: Indica que este job depende de los jobs
composer
ynpm
, por lo que no se ejecutará hasta que la instalación de dependencias PHP y JavaScript haya finalizado correctamente. - steps: Lista los pasos que se ejecutarán en el job:
- Clonar repositorio: Usa la acción
actions/checkout@v4
para clonar el repositorio en el runner y disponer del código fuente necesario para la construcción de la imagen. - Recuperar artifacts: Usa la acción
actions/download-artifact@v4
para descargar los artefactos generados en jobs previos, como dependencias o archivos de compilación. - Crear directorio tar_images: Ejecuta el comando
mkdir -p tar_images
para crear el directorio donde se almacenará la imagen de contenedor en formato tar. - Build Docker image with Kaniko: Utiliza la imagen de Kaniko (
gcr.io/kaniko-project/executor:latest
) para construir la imagen de contenedor sin requerir privilegios de root ni demonio de Docker. Se especifican los siguientes argumentos:--context .
: Define el directorio raíz del repositorio como contexto de construcción.--dockerfile docker/nginx/Dockerfile
: Especifica la ubicación del Dockerfile a utilizar.--destination harbor.opensecdevops.com/osdo/osdo-app:${{ github.sha }}
: Indica el destino de la imagen en el registro de contenedores, utilizando el hash del commit como tag.--tar-path tar_images/osdo_app.tar
: Define la ruta donde se guardará la imagen como archivo tar.--no-push
: Indica que la imagen no se subirá automáticamente al registro, sino que se almacenará localmente.
- Upload Docker image tar: Usa la acción
actions/upload-artifact@v4
para subir el archivo tar generado como artefacto del workflow, permitiendo su descarga o uso en etapas posteriores. Se especifica el nombre del artefacto (docker_image
), la ruta (tar_images/
) y el tiempo de retención (retention-days: 1
).
- Clonar repositorio: Usa la acción
Jenkins
stage('Build Image with Kaniko') {
environment {
DOCKER_REGISTRY_URL = 'harbor.opensecdevops.com'
}
steps {
unstash 'deps'
script {
if (env.TAG_NAME) {
env.IMAGE_TAG = env.TAG_NAME
} else {
def sha = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
env.IMAGE_TAG = "${env.BRANCH_NAME}-${sha}"
}
sh 'mkdir -p tar_images'
sh """
docker run --rm \
-v /workspace/${JOB_NAME}:/app \
-w /app \
gcr.io/kaniko-project/executor:latest \
--context /app \
--dockerfile /app/docker/nginx/Dockerfile \
--destination ${DOCKER_REGISTRY_URL}/osdo/osdo-app:\${IMAGE_TAG} \
--no-push \
--tar-path tar_images/osdo_app.tar
"""
}
}
post {
success {
archiveArtifacts artifacts: 'tar_images/**', fingerprint: true
stash name: 'docker-image', includes: 'tar_images/osdo_app.tar'
}
}
}
-
environment:
Define variables de entorno necesarias para el proceso:DOCKER_REGISTRY_URL
: URL del registro de contenedores donde se almacenará la imagen generada.
-
unstash 'deps':
Recupera las dependencias previamente almacenadas en una etapa anterior del pipeline, asegurando que estén disponibles para la construcción de la imagen. -
script:
Ejecuta un bloque de instrucciones en Groovy para preparar y construir la imagen:- Comprueba si existe una variable
TAG_NAME
(por ejemplo, para releases); si existe, la usa como tag de la imagen. Si no, genera un tag basado en el nombre de la rama y el hash corto del commit actual, asegurando la trazabilidad de la imagen. - Ejecuta
mkdir -p tar_images
para crear el directorio donde se almacenará la imagen en formato tar. - Ejecuta el comando
docker run
con la imagen de Kaniko para construir la imagen de contenedor:- Monta el workspace del job en el contenedor (
-v /workspace/${JOB_NAME}:/app
). - Establece el directorio de trabajo (
-w /app
). - Usa Kaniko (
gcr.io/kaniko-project/executor:latest
) para construir la imagen con los siguientes argumentos:--context /app
: Define el contexto de construcción.--dockerfile /app/docker/nginx/Dockerfile
: Especifica la ubicación del Dockerfile.--destination ${DOCKER_REGISTRY_URL}/osdo/osdo-app:${IMAGE_TAG}
: Indica el destino y tag de la imagen.--no-push
: Indica que la imagen no se subirá automáticamente al registro, sino que se almacenará localmente.--tar-path tar_images/osdo_app.tar
: Define la ruta donde se guardará la imagen como archivo tar.
- Monta el workspace del job en el contenedor (
- Comprueba si existe una variable
-
post > success:
Acciones a ejecutar si el stage finaliza correctamente:archiveArtifacts artifacts: 'tar_images/**', fingerprint: true
: Guarda la imagen generada como artefacto del build y asegura la trazabilidad mediante fingerprint.stash name: 'docker-image', includes: 'tar_images/osdo_app.tar'
: Almacena el archivo tar generado en el stash de Jenkins para su uso en etapas posteriores del pipeline.