Ce que j'aurais voulu savoir sur Gitlab CI
18 mai 2025Introduction
Il y a quelques mois je parlais de ma formation Bootcamp pour devenir Ingénieur DevOps. J’y ai utilisé - à nouveau - Gitlab CI (Continuous Integration). Vous savez, cet outil permettant d’exécuter des actions après avoir envoyé votre code/dépôt sur la plateforme Gitlab ?
C’est très utile, par exemple pour lancer les tests sur votre code, vérifier que le code s’exécute dans un environnement précis ou tout simplement vérifier que le code compile. Et si votre dépôt n’est pas du code, par exemple un site web, vous pouvez tester les liens morts ; voire publier votre site ! Les possibilités sont - finalement - nombreuses !
En revanche, un tel outil est parfois déstabilisant. Et des cheveux, j’en ai arrachés ! J’aurais apprécié tomber sur un article explicatif. Avec des astuces. Peut-être que le présent article m’aurait convenu, qui sait !
J’aurai par exemple aimé savoir comment publier facilement un site web, tester localement le fichier .gitlab-ci.yml avant de l’envoyer sur Gitlab, connaître plus d’astuces pour les mots clés Gitlab, savoir utiliser Docker dans Gitlab CI et ce que sont les composants réutilisables.
Ce sont ainsi tous les sujets que nous allons aborder aujourd’hui.
Photo trouvée sur le profil de didier.camus sur Flickr sous Licence Œuvre du domaine public.
Publier rapidement un site statique
Gitlab met à disposition des utilisateurs un espace permettant d’héberger des sites webs statiques. Incroyable n’est-ce pas ? Cet espace est Gitlab Pages.
Comment cela fonctionne ? Il suffit de créer un dépôt Gitlab, d’ajouter un fichier .gitlab-ci.yml contenant la section suivante :
image: busybox
pages:
stage: deploy
script:
- echo "The site will be deployed to $CI_PAGES_URL"
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Code récupéré du projet https://gitlab.com/pages/plain-html.
Cela signifie qu’au terme de la CI/CD (dans l’étape nommée deploy), le contenu du dossier public sera publié sur Gitlab Pages. À quelle adresse ? Imaginons que vous partez d’un dépôt dont l’adresse est : https://gitlab.com/blankoworld/monprojet/
, l’adresse URL d’accès à votre site publié sera : https://blankoworld.gitlab.io/monprojet/
. Pratique non ?
Astuce : Si votre dépôt est privé, vous pouvez quand même rendre votre site public. Il suffit d’aller dans Settings > General, Section « Visibility, project features, permissions » et dans le sous-titre « Pages », activez la fonctionnalité. Et dans le menu déroulant à côté, choisissez « Everyone ». N’oubliez pas de sauvegarder cette configuration. Le code sera privé, le site web statique public !
Pour plus d’exemple, veuillez vous rendre sur la page Gitlab présentant la liste de projets utilisant Gitlab Pages.
Tester avant d’envoyer sur le dépôt ?
Le truc vraiment embêtant avec les fichiers .gitlab-ci.yml, c’est qu’on ne peut pas les tester sur notre machine (localement). Pour avancer il faut :
- modifier le fichier .gitlab-ci.yml,
- le valider (faire un commit),
- l’envoyer sur Gitlab,
- patienter que la pipeline se lance (et parfois se termine),
- bénéficier du résultat ou, dans la plupart des cas, recommencer à l’étape 1…
À une époque on pouvait utiliser une commande gitlab-runner exec
en local. Mais celle-ci a été supprimée : https://gitlab.com/gitlab-org/gitlab-runner/-/commit/f8508c924f80b104ec7353353e6ad0edb5daae66 .
Suivant ce que nous faisons dans la CI/CD de Gitlab, il est possible d’utiliser un outil bien pratique nommé gitlab-ci-local : gitlab-ci-local.
Vous trouverez quelques détails de gitlab-ci-local sur mon recueil d’astuces.
Généralités
Voici quelques pistes intéressantes sur le sujet Gitlab :
- Une documentation de départ est : https://docs.gitlab.com/topics/build_your_application/. Elle permet d’en savoir plus sur la syntaxe de gitlab-ci.yaml, les variables pré-définies ou encore le fonctionnement d’un pipeline dans Gitlab CI,
- Toujours utiles : les actions que je nomme comme « globales ». Par exemple les mots clés
image
,variables
oubefore_script
peuvent être utilisés en début du fichier pour définir des actions ou des valeurs qui seront utilisées dans toutes les étapes du pipeline. Ce qui peut être un avantage, ou un inconvénient. Exemple :image: ubuntu:latest
va définir que toutes les étapes se lanceront dans un docker partant de l’image Ubuntu, - Entrées/sorties : un artefact = une sortie. C’est à dire des fichiers utilisables/disponibles pour les étapes suivantes (donc en entrée pour les autres étapes) en utilisant le mot clé dependencies (Cf. https://docs.gitlab.com/ci/jobs/job_artifacts/#fetching-artifacts). Sauf si
dependencies = []
est utilisé. - Utiliser des variables globales en début du fichier (par exemple pour les numéros de versions) fait gagner du temps sur le long terme. Exemple :
variables:
DOCKER_VERSION: "27.3.1"
UBUNTU_VERSION: "24.04"
- Concernant le mot clé script :
- si on veut écrire plusieurs lignes, utiliser la syntaxe suivante :
script: - echo "première étape des scripts" - | echo "première ligne" echo "seconde ligne" echo "etc."
- limiter à 10 lignes maximum,
- si on utilise la syntaxe pour écrire plusieurs lignes, le debug est plus difficile
- Pour organiser les étapes, on peut donner à chacune d’elle une étape pré-requise en utilisant le mot clé « needs », cela permet de chaîner les étapes dans un certain ordre. Exemple : si on veut que l’étape « deploy » se fasse après « compile », alors à la fin de l’étape « deploy » on met
needs: [compile]
.
Le Cas Docker
Création d’une image Docker… dans un conteneur Docker
Dans la situation où vous voudriez fabriquer des images Docker, vous allez être confrontés à plusieurs problématiques :
- il faut utiliser des commandes
docker
pour créer des images, - mais la plupart des Gitlab Runner exécutent les étapes de Gitlab CI dans un Docker,
- donc on se retrouve à vouloir exécuter des commandes
docker
dans un environnement Docker.
Vous voyez le problème ?
Pour contourner cette situation il suffit d’utiliser Docker-in-Docker.
En somme le début du fichier .gitlab-ci.yml ressemblera à :
variables:
DOCKER_VERSION: "27.4.1"
image: docker:$DOCKER_VERSION
services:
- docker:$DOCKER_VERSION-dind
S’identifier
Pour utiliser les dépôts de conteneurs de Gitlab, rien de plus simple il suffit d’écrire le code suivant dans le fichier .gitlab-ci.yml :
before_script:
- docker info
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
Nul besoin de renseigner les variables. Elles sont renseignées par Gitlab CI.
Construire l’image
Pour construire l’image cela va ressembler à :
variables:
CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
build-image:
stage: build
script:
- docker pull "$CONTAINER_TEST_IMAGE" || true
- docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t $CONTAINER_TEST_IMAGE .
- docker push $CONTAINER_TEST_IMAGE
On part du principe que le fichier Dockerfile est situé à la racine de votre projet Gitlab.
CONTAINER_TEST_IMAGE est une variable globale construite à partir des variables pré-définies de Gitlab CI.
Pousser l’image sur le dépôt
Dans cette situation nous sommes contents d’avoir déjà ajouté l’authentification aux dépôts de conteneurs Gitlab.
Cette fois on fait une étape pour récupérer l’image précédente et lui donner un nouveau nom :
push-image:
stage: push
script:
- export IMAGE_TAG="$(date +'%Y%m%d')-${CI_COMMIT_SHORT_SHA}"
- docker pull $CONTAINER_TEST_IMAGE
- docker tag $CONTAINER_TEST_IMAGE $CI_REGISTRY_IMAGE:$IMAGE_TAG
- docker push $CI_REGISTRY_IMAGE:$IMAGE_TAG
rules:
- if: $CI_COMMIT_BRANCH == "main"
L’idée est :
- de créer un nom de tag pour l’image (variable IMAGE_TAG),
- récupérer l’image précédente - puisque les étapes d’un fichier .gitlab-ci.yml s’exécutent dans des conteneurs isolés les uns des autres,
- apposer un nouveau tag sur l’image récupérée,
- publier le résultat en poussant l’image ainsi étiquetée.
Ceci ne s’exécute que si la branche est nommée main. Donc chaque commit sur cette branche générera une image Docker et un tag.
Ordre d’exécution des étapes
Afin que les deux étapes précédentes s’exécutent dans un certain ordre, ne pas oublier les lignes suivantes dans le fichier .gitlab-ci.yml :
stages:
- build
- push
Comme si ça ne suffisait pas…
En outre, voici d’autres éléments à rajouter dans son fichier .gitlab-ci.yml :
variables:
# Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_CERTDIR: "/certs"
Ces lignes permettent de renseigner un autre accès à l’API Docker pour lancer les commandes docker
.
Les composants réutilisables
Gitlab CI offre la possibilité d’utiliser des composants réutilisables pour agrémenter les étapes de son fichier .gitlab-ci.yml. Ceci évite de réinventer la roue (en codant soi-même).
Plusieurs composants sont disponibles sur la page Gitlab components.
Exemple d’utilisation d’un composant :
include:
- component: gitlab.com/components/container-scanning/container-scanning@5.1.0
C’est très utile dans certaines situations comme pour tester des fichiers Terraform (avec le composant OpenTofu), le composant Go, le composant Rust ou même utiliser les fonctionnalités Autodevops de Gitlab.
Conclusion
Au premier abord Gitlab CI paraît complexe et maigre en fonctionnalités. Cependant la lecture de la documentation (très fournie !) donne rapidement un aperçu bien plus avantageux de cet outil. On y découvre les composants réutilisables, les mots clés image
, variables
, before_script
, les artefacts (sorties), les variables globales, le déploiement de sites statiques et j’en passe !
Certaines difficultés telles que Docker viennent s’immiscer dans nos essais. Mais une fois les obstacles franchis c’est un outil très satisfaisant. Je l’apprécie.
Je serais ravi de tomber plus souvent sur des articles décrivant ses fonctionnalités. J’espère participer à une diffusion plus grande de la connaissance Gitlab CI et, qui sait, peut-être partagerais-je prochainement d’autres astuces ?