Comment créer des images Docker dans un pipeline GitLab CI

0
355

Un cas d'utilisation courant des pipelines CI consiste à créer les images Docker que vous utiliserez pour déployer votre application . GitLab CI est un excellent choix pour cela car il prend en charge un service de proxy pull intégré, ce qui signifie des pipelines plus rapides, et un registre intégré pour stocker vos images construites.

Dans ce guide, nous allons vous montrer comment configurer des builds Docker qui utilisent les deux fonctionnalités ci-dessus. Les étapes à suivre varient légèrement en fonction du type d'exécuteur GitLab Runner que vous utiliserez pour votre pipeline. Nous aborderons les exécuteurs Shell et Docker ci-dessous.

Construire avec l'exécuteur Shell

Si vous" Lorsque vous utilisez l'exécuteur Shell, assurez-vous que Docker est installé sur la machine qui héberge votre exécuteur. L'exécuteur fonctionne en exécutant des commandes shell régulières à l'aide du binaire docker sur l'hôte du Runner.

Dirigez-vous vers le référentiel Git du projet pour lequel vous souhaitez créer des images. Créez un fichier .gitlab-ci.yml à la racine du référentiel. Ce fichier définit le pipeline CI GitLab qui s'exécutera lorsque vous pousserez des modifications dans votre projet.

Ajoutez le contenu suivant au fichier :

étapes : – build docker_build : étape : script de génération : – docker build -t example.com/example-image:latest . – docker push example.com/example-image:latest

Cette configuration simpliste est suffisante pour démontrer les bases des créations d'images alimentées par pipeline. GitLab clone automatiquement votre référentiel Git dans l'environnement de construction afin que l'exécution de docker build utilise le Dockerfile de votre projet et rende le contenu du référentiel disponible en tant que contexte de construction.

Publicité

Après la construction est terminée, vous pouvez docker pousser l'image vers votre registre. Sinon, il ne serait disponible que pour l'installation Docker locale qui a exécuté la construction. Si vous utilisez un registre privé, exécutez d'abord docker login pour fournir les informations d'authentification appropriées :

script : – docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD

Définissez les valeurs des deux variables d'identification en vous rendant dans Paramètres > CI/CD > Variables dans l'interface utilisateur Web GitLab. Cliquez sur le bouton bleu “Ajouter une variable” pour créer une nouvelle variable et attribuer une valeur. GitLab rendra ces variables disponibles dans l'environnement shell utilisé pour exécuter votre tâche.

Construire avec Docker Executor

L'exécuteur Docker de GitLab Runner est couramment utilisé pour fournir un environnement complètement propre pour chaque travail. Le travail s'exécutera dans un conteneur isolé afin que le binaire docker sur l'hôte Runner soit inaccessible.

L'exécuteur Docker vous propose deux stratégies possibles pour créer votre image : soit utiliser Docker-in-Docker, soit lier le socket Docker de l'hôte à l'environnement de construction du Runner. Vous utilisez ensuite l'image officielle du conteneur Docker comme image de votre travail, ce qui rend la commande docker disponible dans votre script CI.

Docker-in-Docker

L'utilisation de Docker-in-Docker (DinD) pour créer vos images vous offre un environnement entièrement isolé pour chaque tâche. Le processus Docker qui effectue la construction sera un enfant du conteneur que GitLab Runner crée sur l'hôte pour exécuter la tâche CI.

Vous devez enregistrer votre exécuteur GitLab Runner Docker avec le mode privilégié activé pour utiliser DinD . Ajoutez le drapeau –docker-privileged lorsque vous enregistrez votre runner :

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 Publicité

Dans votre pipeline CI, ajoutez l'image docker:dd en tant que service. Ainsi, Docker est disponible en tant qu'image distincte liée à l'image de la tâche. Vous pourrez utiliser la commande docker pour créer des images à l'aide de l'instance Docker dans le conteneur docker:dind.

services : – docker:dind docker_build : stage : build image : docker:latest script : – docker build -t example-image:latest .

L'utilisation de DinD vous donne des versions entièrement isolées qui ne peuvent pas avoir d'impact les unes sur les autres ou sur votre hôte. L'inconvénient majeur est un comportement de mise en cache plus compliqué : chaque tâche obtient un nouvel environnement dans lequel les couches précédemment créées ne seront pas accessibles. Vous pouvez partiellement résoudre ce problème en essayant d'extraire la version précédente de votre image avant de créer, puis en utilisant l'indicateur de construction –cache-from pour rendre les calques de l'image extraite disponibles en tant que source de cache :

docker_build : étape : 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 .

Supports de liaison de socket

Le montage du socket Docker de votre hôte dans l'environnement de votre tâche est une autre option lorsque vous utilisez l'exécuteur Docker. Cela vous donne une mise en cache transparente et supprime la nécessité d'ajouter le service docker: dind à votre configuration CI.

Pour configurer cela, enregistrez votre Runner avec un indicateur docker-volumes qui lie l'hôte Socket Docker vers /var/run/docker.sock dans les conteneurs de tâches :

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

Désormais, les tâches qui s'exécutent avec l'image docker pourront utiliser le binaire docker normalement. Les opérations se produiront réellement sur votre machine hôte, devenant des frères et sœurs du conteneur de la tâche au lieu d'enfants.

Ceci est en fait similaire à l'utilisation de l'exécuteur de shell avec l'installation Docker de votre hôte. Les images résideront sur l'hôte, ce qui facilitera l'utilisation transparente de la mise en cache de la couche de construction Docker habituelle.

Publicité

Bien que cette approche puisse conduire à des performances plus élevées, à moins de configuration et à aucune des limitations de DinD, elle comporte ses propres problèmes uniques. Les plus importantes d'entre elles sont les implications en matière de sécurité : les tâches peuvent exécuter des commandes Docker arbitraires sur votre hôte Runner, de sorte qu'un projet malveillant dans votre instance GitLab peut exécuter docker run -it malware-image:latest ou docker rm -f $(docker ps -a ) avec des conséquences dévastatrices.

GitLab avertit également que la liaison de socket peut causer des problèmes lorsque les travaux s'exécutent simultanément. Cela se produit lorsque vous comptez sur des conteneurs créés avec des noms spécifiques. Si deux instances d'une tâche s'exécutent en parallèle, la seconde échouera car le nom du conteneur existe déjà sur votre hôte.

Vous devriez envisager d'utiliser DinD à la place si vous pensez que l'un de ces problèmes sera gênant. Bien que DinD ne soit généralement plus recommandé, il peut être plus logique pour les instances GitLab publiques qui exécutent des tâches CI simultanées.

Pousser des images vers le registre de GitLab

Les projets GitLab ont l'option d'un registre intégré que vous pouvez utiliser pour stocker vos images. Vous pouvez afficher le contenu du registre en accédant à Packages & Registres > Container Registry dans la barre latérale de votre projet. Si vous ne voyez pas ce lien, activez le registre en accédant à Paramètres > Général > Visibilité, Projet, Fonctionnalités & Autorisations et activation du “Registre de conteneurs” basculer.

 

GitLab définit automatiquement des variables d'environnement dans vos tâches CI qui vous permettent de référencer votre projet 8217;s registre de conteneurs. Ajustez la section script pour vous connecter au registre et poussez votre image :

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 : le dernier

GitLab génère un ensemble sécurisé d'informations d'identification pour chacune de vos tâches CI. La variable d'environnement $CI_JOB_TOKEN contiendra un jeton d'accès que le travail peut utiliser pour se connecter au registre en tant qu'utilisateur gitlab-ci-token. L'URL du serveur de registre est disponible sous la forme $CI_REGISTRY.

Publicité

La dernière variable, $CI_REGISTRY_IMAGE, fournit le chemin complet vers le registre de conteneurs de votre projet. C'est une base appropriée pour vos balises d'image. Vous pouvez étendre cette variable pour créer des sous-dépôts, tels que $CI_REGISTRY_IMAGE/production/api:latest.

 

D'autres clients Docker peuvent extraire des images du registre en s'authentifiant à l'aide d'un jeton d'accès. Vous pouvez les générer dans les Paramètres > de votre projet. Accédez à l'écran des jetons. Ajoutez la portée read_registry, puis utilisez les informations d'identification affichées pour vous connecter au docker dans le registre de votre projet.

Utilisation du proxy de dépendance de GitLab

h2>

Le proxy de dépendance de GitLab fournit une couche de mise en cache pour les images en amont que vous extrayez de Docker Hub. Il vous aide à rester dans les limites de débit de Docker Hub en extrayant uniquement le contenu des images lorsqu'elles ont réellement changé. Cela améliorera également les performances de vos builds.

Le proxy de dépendance est activé au niveau du groupe GitLab en allant dans Paramètres > Forfaits & Registres > Proxy de dépendance. Une fois activé, préfixez les références d'image dans votre fichier .gitlab-ci.yml avec $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX pour les faire passer par le proxy :

docker_build : stage : build image : $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:latest services : – nom : $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:dind alias : docker

C'est tout ! GitLab Runner se connecte automatiquement au registre du proxy de dépendance, il n'est donc pas nécessaire de fournir manuellement vos informations d'identification.

GitLab mettra désormais en cache vos images, vous offrant des performances améliorées ainsi qu'une résilience aux pannes de réseau. Notez que la définition des services a également dû être ajustée – les variables d'environnement ne fonctionnent pas avec le formulaire en ligne utilisé précédemment, donc le nom complet de l'image doit être spécifié, puis un alias de commande à référencer dans votre section de script.

Publicité

Bien que nous ayons maintenant configuré le proxy pour les images directement utilisées par nos étapes de travail, d'autres travaux sont nécessaires pour ajouter la prise en charge de l'image de base dans le Dockerfile à créer. Une instruction régulière comme celle-ci ne passera pas par le proxy :

FROM ubuntu:latest

Pour ajouter cette dernière pièce, utilisez les arguments de construction de Docker pour rendre l'URL du proxy de dépendance disponible lors de l'étape le Dockerfile :

ARG GITLAB_DEPENDENCY_PROXY FROM ${GITLAB_DEPENDENCY_PROXY}/ubuntu:latest

Modifiez ensuite votre commande docker build pour définir la valeur de la variable :

script : > – build docker –build-arg GITLAB_DEPENDENCY_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX} -t example-image:latest .

Désormais, votre image de base sera également extraite via le proxy de dépendance.

Résumé

Les builds d'image Docker sont facilement intégrés dans vos pipelines GitLab CI. Après la configuration initiale de Runner, les commandes docker build et docker push dans la section de script de votre travail sont tout ce dont vous avez besoin pour créer une image avec le Dockerfile dans votre référentiel. Le registre de conteneurs intégré de GitLab vous offre un stockage privé pour les images de votre projet.

Au-delà des versions de base, il vaut la peine d'intégrer le proxy de dépendance de GitLab pour accélérer les performances et éviter d'atteindre les limites de débit de Docker Hub. Vous devez également vérifier la sécurité de votre installation en évaluant si la méthode que vous avez sélectionnée permet à des projets non approuvés d'exécuter des commandes sur votre hôte Runner. Bien qu'il comporte ses propres problèmes, Docker-in-Docker est l'approche la plus sûre lorsque votre instance GitLab est publiquement accessible ou accessible par une large base d'utilisateurs.