Un caso de uso común para las canalizaciones de CI es crear las imágenes de Docker que usará para implementar su aplicación. GitLab CI es una excelente opción para esto, ya que admite un servicio de proxy de extracción integrado, lo que significa canalizaciones más rápidas y un registro integrado para almacenar las imágenes creadas.
En esta guía, le mostraremos cómo configurar compilaciones de Docker que utilicen las dos funciones anteriores. Los pasos que debe seguir varían ligeramente según el tipo de ejecutor de GitLab Runner que utilizará para su canalización. Cubriremos los ejecutores de Shell y Docker a continuación.
Construyendo con el ejecutor Shell
Si está utilizando el ejecutor de Shell, asegúrese de tener Docker instalado en la máquina que aloja su ejecutor. El ejecutor funciona ejecutando comandos de shell regulares utilizando el binario de Docker en el host del Runner.
Dirígete al repositorio de Git del proyecto para el que deseas crear imágenes. Cree un archivo .gitlab-ci.yml en la raíz del repositorio. Este archivo define la canalización de CI de GitLab que se ejecutará cuando envíe cambios a su proyecto.
Agregue el siguiente contenido al archivo:
stages:- build
docker_build:
stage: build
script:
- docker build -t example.com/example-image:latest .
- docker push example.com/example-image:latest
Esta configuración simplista es suficiente para demostrar los conceptos básicos de la creación de imágenes impulsadas por canalizaciones. GitLab clona automáticamente su repositorio Git en el entorno de compilación, por lo que ejecutar Docker Build utilizará el Dockerfile de su proyecto y hará que el contenido del repositorio esté disponible como contexto de compilación.
Una vez completada la compilación, puede insertar la imagen en su registro mediante Docker. De lo contrario, solo estaría disponible para la instalación local de Docker que ejecutó la compilación. Si está utilizando un registro privado, primero ejecute Docker Login para proporcionar los detalles de autenticación adecuados:
script:- docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD
Defina los valores de las dos variables de credenciales dirigiéndose a Configuración > CI/CD > Variables en la interfaz de usuario web de GitLab. Haga clic en el botón azul «Agregar variable» para crear una nueva variable y asignar un valor. GitLab hará que estas variables estén disponibles en el entorno de shell utilizado para ejecutar su trabajo.
Construyendo con Docker Executor
El ejecutor Docker de GitLab Runner se usa comúnmente para proporcionar un entorno completamente limpio para cada trabajo. El trabajo se ejecutará en un contenedor aislado, por lo que el binario de la ventana acoplable en el host Runner será inaccesible.
El ejecutor de Docker le ofrece dos estrategias posibles para crear su imagen: usar Docker-in-Docker o vincular el socket Docker del host al entorno de compilación de Runner. Luego usa la imagen oficial del contenedor Docker como imagen de su trabajo, haciendo que el comando Docker esté disponible en su script CI.
Docker en Docker
El uso de Docker-in-Docker (DinD) para crear sus imágenes le brinda un entorno completamente aislado para cada trabajo. El proceso Docker que realiza la compilación será hijo del contenedor que GitLab Runner crea en el host para ejecutar el trabajo de CI.
Debe registrar su ejecutor Docker de GitLab Runner con el modo privilegiado habilitado para usar DinD. Agregue la bandera –docker-privileged cuando registre a su corredor:
sudo gitlab-runner register -n--url https://example.com
--registration-token $GITLAB_REGISTRATION_TOKEN
--executor docker
--description "Docker Runner"
--docker-image "docker:20.10"
--docker-volumes "/certs/client"
--docker-privileged
Dentro de su proceso de CI, agregue la imagen docker:dind como servicio. Esto hace que Docker esté disponible como una imagen separada vinculada a la imagen del trabajo. Podrás usar el comando Docker para crear imágenes usando la instancia de Docker en el contenedor Docker:dind.
services:- docker:dind
docker_build:
stage: build
image: docker:latest
script:
- docker build -t example-image:latest .
El uso de DinD le brinda compilaciones completamente aisladas que no pueden afectarse entre sí ni a su host. El principal inconveniente es un comportamiento de almacenamiento en caché más complicado: cada trabajo obtiene un nuevo entorno donde no se podrá acceder a las capas creadas previamente. Puedes solucionar esto parcialmente intentando extraer la versión anterior de tu imagen antes de compilarla y luego usando –cache-from construir bandera para que las capas de la imagen extraída estén disponibles como fuente de caché:
docker_build:stage: build
image: docker:latest
script:
- docker pull $CI_REGISTRY_IMAGE:latest || true
- docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:latest .
Montajes de enlace de zócalo
Montar el socket Docker de su host en el entorno de su trabajo es una opción alternativa cuando utiliza el ejecutor Docker. Esto le brinda un almacenamiento en caché perfecto y elimina la necesidad de agregar el servicio docker:dind a su configuración de CI.
Para configurar esto, registre su Runner con un indicador docker-volumes que vincule el socket Docker del host a /var/run/docker.sock dentro de los contenedores de trabajos:
sudo gitlab-runner register -n--url https://example.com
--registration-token $GITLAB_REGISTRATION_TOKEN
--executor docker
--description "Docker Runner"
--docker-image "docker:20.10"
--docker-volumes /var/run/docker.sock:/var/run/docker.sock
Ahora los trabajos que se ejecutan con la imagen de la ventana acoplable podrán usar el binario de la ventana acoplable con normalidad. Las operaciones realmente ocurrirán en su máquina host, convirtiéndose en hermanos del contenedor del trabajo en lugar de hijos.
Esto es efectivamente similar a usar el ejecutor de shell con la instalación de Docker de su host. Las imágenes residirán en el host, lo que facilitará el uso fluido del almacenamiento en caché de la capa de compilación de Docker habitual.
Si bien este enfoque puede conducir a un mayor rendimiento, menos configuración y ninguna de las limitaciones de DinD, tiene sus propios problemas únicos. Las más destacadas son las implicaciones de seguridad: los trabajos podrían ejecutar comandos Docker arbitrarios en su host Runner, por lo que un proyecto malicioso en su instancia de GitLab podría ejecutar docker run -it malicioso-image:latest o docker rm -f $(docker ps -a ) con consecuencias devastadoras.
GitLab también advierte ese enlace de socket puede causar problemas cuando los trabajos se ejecutan simultáneamente. Esto ocurre cuando depende de que los contenedores se creen con nombres específicos. Si dos instancias de un trabajo se ejecutan en paralelo, la segunda fallará porque el nombre del contenedor ya existirá en su host.
Debería considerar usar DinD en su lugar si espera que cualquiera de estos problemas sea problemático. Mientras que DinD es ya no se recomienda generalmentepuede tener más sentido para instancias públicas de GitLab que ejecutan trabajos de CI simultáneos.
Enviar imágenes al registro de GitLab
Los proyectos de GitLab tienen la opción de un registro integrado que puedes utilizar para almacenar tus imágenes. Puede ver el contenido del registro navegando a Paquetes y registros > Registro de contenedor en la barra lateral de su proyecto. Si no ve este enlace, habilite el registro yendo a Configuración > General > Visibilidad, Proyecto, Funciones y Permisos y activando la opción «Registro de contenedor».
GitLab establece automáticamente variables de entorno en sus trabajos de CI que le permiten hacer referencia al registro de contenedores de su proyecto. Ajuste la sección del script para iniciar sesión en el registro y enviar su imagen:
script:- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:latest .
- docker push $CI_REGISTRY_IMAGE:latest
GitLab genera un conjunto seguro de credenciales para cada uno de sus trabajos de CI. La variable de entorno $CI_JOB_TOKEN contendrá un token de acceso que el trabajo puede usar para conectarse al registro como usuario de gitlab-ci-token. La URL del servidor de registro está disponible como $CI_REGISTRY.
La variable final, $CI_REGISTRY_IMAGE, proporciona la ruta completa al registro de contenedor de su proyecto. Esta es una base adecuada para sus etiquetas de imágenes. Puede ampliar esta variable para crear subrepositorios, como $CI_REGISTRY_IMAGE/production/api:latest.
Otros clientes de Docker pueden extraer imágenes del registro autenticándose mediante un token de acceso. Puedes generarlos en la pantalla Configuración > Tokens de acceso de tu proyecto. Agregue el alcance read_registry, luego use las credenciales mostradas para iniciar sesión en el registro de su proyecto.
Usando la dependencia de GitLab Proxy
Dependencia de GitLab Proxy proporciona una capa de almacenamiento en caché para las imágenes ascendentes que extrae de Docker Hub. Te ayuda a permanecer dentro Estibador Hublímites de tarifas extrayendo únicamente el contenido de las imágenes cuando realmente han cambiado. Esto también mejorará el rendimiento de sus compilaciones.
La dependencia Proxy se activa en el nivel de grupo de GitLab dirigiéndose a Configuración > Paquetes y registros > Dependencia Proxy. Una vez que esté habilitado, prefije las referencias de imágenes en su archivo .gitlab-ci.yml con $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX para pasarlas a través del proxy:
docker_build:stage: build
image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:latest
services:
- name: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:dind
alias: docker
¡Eso es todo al respecto! GitLab Runner inicia sesión automáticamente en el registro de proxy de dependencia, por lo que no es necesario proporcionar manualmente sus credenciales.
GitLab ahora almacenará en caché sus imágenes, brindándole un rendimiento mejorado y resistencia a las interrupciones de la red. Note que la definición de servicios también tuvo que ajustarse: las variables de entorno no funcionan con el formulario en línea utilizado anteriormente, por lo que se debe especificar el nombre completo de la imagen y luego un alias de comando al que hacer referencia en la sección de secuencia de comandos.
Si bien ahora hemos configurado el proxy para las imágenes utilizadas directamente en nuestras etapas de trabajo, se necesita más trabajo para agregar soporte para la imagen base en el Dockerfile para su compilación. Una instrucción normal como esta no pasará por el proxy:
FROM ubuntu:latest
Para agregar esta pieza final, use los argumentos de compilación de Docker para que la URL del proxy de dependencia esté disponible al recorrer el Dockerfile:
ARG GITLAB_DEPENDENCY_PROXYFROM ${GITLAB_DEPENDENCY_PROXY}/ubuntu:latest
Luego modifique el comando de compilación de Docker para definir el valor de la variable:
script:>
- docker build
--build-arg GITLAB_DEPENDENCY_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}
-t example-image:latest .
Ahora su imagen base también pasará por el proxy de dependencia.
Resumen
Las compilaciones de imágenes de Docker se integran fácilmente en sus canalizaciones de CI de GitLab. Después de la configuración inicial de Runner, todo lo que necesita para crear una imagen con Dockerfile en su repositorio son los comandos docker build y docker push en la sección de script de su trabajo. El registro de contenedores integrado de GitLab le brinda almacenamiento privado para las imágenes de su proyecto.
Más allá de las compilaciones básicas, vale la pena integrar el proxy de dependencia de GitLab para acelerar el rendimiento y evitar afectar a Docker. Hub límites de tarifas. También debe verificar la seguridad de su instalación evaluando si el método seleccionado permite que proyectos que no son de confianza ejecuten comandos en su host Runner. Aunque conlleva sus propios problemas, Docker-in-Docker es el enfoque más seguro cuando su instancia de GitLab es de acceso público o accede a ella una gran base de usuarios.