Maximize Page
Tech & DevOps HubEspace Tech & DevOps: Explorez le monde du Dev, du Cloud et des outils DevOps à travers nos articles et discussions Explore the world of development, the cloud and DevOps tools

Installer et configurer un GitLab Runner local

Date de l'article:02-06-2026
Docker Desktop CI/CD Gitlab
Pas de pipeline sans exécuteur. Nous allons installer, configurer et enregistrer un GitLab Runner local avec Docker Desktop sous Windows pour valider les pipelines directement depuis notre machine.
Dans l'article précédent, nous avons préparé le projet GitLab et vérifié que les runners SaaS étaient capables d'exécuter un premier pipeline.
Cela reste vrai un certain temps. En effet, le plan "Free" dispose de 400 minutes de calcul par mois pour les runners hébergés par GitLab.
Une fois ce quota atteint, l'exécution des jobs concernés est limitée jusqu'au renouvellement du quota, sauf achat de minutes supplémentaires.
Lorsqu'on développe une chaîne CI/CD, ces minutes sont rapidement consommées : chaque correction, chaque essai et chaque exécution de pipeline consomment des minutes.
Pour disposer d'une alternative lorsque le quota des runners GitLab est épuisé, nous allons installer un GitLab Runner en local. Les pipelines pourront alors être exécutés sur notre propre machine, sans consommer les "compute minutes" des runners hébergés par GitLab.
En contrepartie, leur exécution dépendra désormais des ressources et de la disponibilité de notre machine locale.
Runner local: avantages et contreparties
Runner hébergé par GitLab Runner local
Pas d'infrastructure à maintenir Machine à maintenir
Disponible côté GitLab Uniquement si la machine est disponible
Consomme le quota Free Pas de consommation de ce quota
Environnement maîtrisé par GitLab Environnement sous notre contrôle
Infrastructure externe Dépend de Docker Desktop / Windows
Isolation gérée par GitLab Il faut gérer la sécurité
Le runner local ne remplace pas sans contrepartie l'infrastructure GitLab: il déplace une partie de la responsabilité d'exploitation vers la machine qui l'héberge.
Installation et configuration
Prérequis (Windows)
Dans l'article précédent, nous avons identifié les outils qui composeront les futurs pipelines :
Maven - Trivy - Semgrep - PostgreSQL - Newman - K6 - Docker… Plusieurs de ces étapes utilisent directement Docker, le runner devra donc être capable d'exécuter des conteneurs.
Le choix de l'exécuteur est une décision importante : il détermine l'environnement dans lequel les jobs seront exécutés.
Docker permet d'isoler les environnements d'exécution et de rapprocher la CI de l'écosystème de conteneurs utilisé par l'application.

1. Installer le runner (localement)
1. Téléchargez le binaire (Windows) : gitlab-runner-windows-amd64
2. Créez un dossier (PowerShell) :
cd C:\
mkdir GitLab-Runner
cd GitLab-Runner
3. Copiez le fichier téléchargé dans le dossier C:\GitLab-Runner,
   puis renommez-le en: gitlab-runner.exe
4. Vérifiez la version (PowerShell) :
 .\gitlab-runner.exe --version
#output
Version:      19.1.1
Git revision: 24b9b726
Git branch:   19-1-stable
GO version:   go1.26.3
Built:        2026-06-25T11:31:53Z
OS/Arch:      windows/amd64

2. Configurer le runner
Dans GitLab, allez dans Settings → CI/CD → Runners , cliquez sur "New project runner", section "Create a project runner"
Définir :
Tags: local-docker
Description
Executor: Docker
GitLab affichera ensuite une commande →
Copy and past the following command into your command line to register a runner.
$ gitlab-runner register
  --url https://gitlab.com
  --token glrt-xxxxxxxxxxxxxxxx
Attention : GitLab n'affiche le token que pendant un court laps de temps.
Le token d'authentification du runner est une information sensible.
Il est stocké dans le fichier config.toml et ne doit jamais être publié dans un dépôt, une capture d'écran ou un article.

3. Enregistrer le runner
Cette étape associe le runner installé localement au projet GitLab. Une fois cette opération effectuée, GitLab pourra lui envoyer les jobs à exécuter.
Via PowerShell (en mode administrateur), entrez la commande donnée précédemment :
.\gitlab-runner register  --url https://gitlab.com  --token glrt-xxxxxxxxxxxxxxxx
PS C:\GitLab-Runner> .\gitlab-runner register  --url https://gitlab.com  --token  glrt-xxxxxxxxxxxxxxxx
Enter the GitLab instance URL (for example, https://gitlab.com/):
https://gitlab.com:
Verifying runner... is valid    correlation_id=xxxxxxxxxxxxxx-BRU runner=xxx runner_name=DESKTOP-MA4VTLF
Aux questions, répondez :
Enter a name for the runner. This is stored only in the local config.toml file:
 [DESKTOP-MA4VTLF]: local-docker

Enter an executor: kubernetes, shell, custom, docker-autoscaler, ssh, parallels, virtualbox, instance, docker, docker-windows, docker + machine:
 [DESKTOP-MA4VTLF]: docker

Enter the default Docker image (for example, ruby:3.3):
 [DESKTOP-MA4VTLF]: alpine:3.22
Il validera ensuite l'enregistrement et affichera le chemin du fichier de configuration :
Runner registered successfully. Feel free to start it, but if it's running already the config should be
automatically reloaded! Configuration (with the authentication token) was saved in "C:\\GitLab-Runner\\config.toml"
Entrez ensuite la commande d'installation :
.\gitlab-runner.exe install
#output
PS C:\GitLab-Runner> .\gitlab-runner.exe install
Runtime platform     arch=amd64 os=windows pid=12356 
revision=24b9b726 version=19.1.1

4. Modifier le fichier de configuration
Ouvrez le fichier C:\GitLab-Runner\config.toml dans l'éditeur de votre choix.
Configuration par défaut
concurrent = 1
check_interval = 0
connection_max_age = "15m0s"
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "local-docker"
  url = "https://gitlab.com"
  id = 12345678
  token = "glrt-xxxxxxxxxxxxxxxx"
  token_obtained_at = 2026-07-27T21:13:03Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "docker"

  [runners.cache]
    MaxUploadedArchiveSize = 0
    [runners.cache.s3]
      AssumeRoleMaxConcurrency = 0
    [runners.cache.gcs]
    [runners.cache.azure]

  [runners.docker]
    tls_verify = false
    image = "alpine:3.22"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    volume_keep = false
    shm_size = 0
    network_mtu = 0
Configuration spécifique au projet
Après une mise à jour de Docker Desktop, les conteneurs créés par GitLab Runner ne partageaient plus correctement leur réseau. L'ajout de :
environment = ["FF_NETWORK_PER_BUILD=1"]
au [[runners]] a permis de retrouver le comportement attendu.
→ Cette option demande à GitLab Runner de créer un réseau Docker dédié pour chaque job, ce qui améliore notamment l'isolation réseau entre les jobs et les services.

Les autres options à modifier :
privileged = true
volumes = ["/cache", "/certs/client"]
L'option "privileged=true" est nécessaire pour les jobs qui utiliseront Docker-in-Docker. Elle augmente cependant le niveau de privilège accordé aux conteneurs et réduit l'isolation vis-à-vis de l'hôte.
Redémarrer le runner après les changements :
.\gitlab-runner restart
.\gitlab-runner.exe status
#output
PS C:\GitLab-Runner> .\gitlab-runner.exe status
Runtime platform    arch=amd64 os=windows pid=15092 revision=24b9b726 version=19.1.1

gitlab-runner: Service is running
Dans ce projet, le runner est volontairement dédié à mon environnement de développement local. La configuration (privileged = true) ne devrait pas être transposée telle quelle à un runner partagé entre plusieurs projets ou à un environnement de production sans analyse de sécurité supplémentaire.

Vérifications
Dans Docker
Ou, depuis un terminal (votre IDE) :
docker version
docker ps
ou, via l'interface de Docker Desktop, vous devriez voir les runners tourner dans les conteneurs (runner-ccqz... running).
C'est de cette manière que l'on identifie le conteneur en cours d'exécution
(voir l'exécution du conteneur Docker)
Dans GitLab
Depuis le projet Settings → CI/CD → Runners,
onglet "Assigned project runners" :
#54252504 (CCQZhsWB)   Project   configuration
Version 19.1.1    local-docker
Last contact: 18 minutes ago    2a02:2788:11a8:36:3868:1dd4:c867:629
C'est ici que vous avez la possibilité de gérer plusieurs runners, de les mettre en route, ou en pause.
Astuce : le runner local constitue une alternative aux runners GitLab lorsque le quota mensuel est épuisé.
Lorsque le quota GitLab est à nouveau disponible, il suffit de ne pas démarrer Docker Desktop : les pipelines pourront alors être exécutés normalement par les runners hébergés par GitLab.

5. Exécuter les jobs
Les jobs actuels utilisent les runners d'instance de GitLab, car ils n'ont pas de tag spécifique. Deux options s'offrent à moi :
Option A (la plus simple) : autoriser le runner local à exécuter les jobs sans tag
Dans les paramètres du runner: Settings → CI/CD → Runners
Cochez: Run untagged jobs
Pratique si on n'utilise qu'un seul projet.
Option B (plus propre) : ajouter un tag, uniquement sur certains jobs
staging-build:
  tags:
    - local-docker
Intéressante lorsque plusieurs runners sont disponibles, car les tags permettent de contrôler le routage des jobs vers l'environnement d'exécution approprié.
Dans cette série, je laisse volontairement les jobs sans tag afin que l'ensemble des pipelines puisse être exécuté par le runner local.
Les pipelines étant encore en cours de construction, cela simplifie les tests et évite d'utiliser inutilement les runners SaaS.
Une fois les pipelines stabilisés, il sera toujours possible d'introduire des tags afin de répartir les jobs entre plusieurs runners.
L'exécution du pipeline suppose que Docker Desktop soit ouvert.
Dès que vous poussez la branche, le pipeline se met en route et vous verrez les conteneurs utilisés dans Docker Desktop.
exécution d'un conteneur dans Docker Desktop
Runner hébergé par GitLab vs runner local : les différences
Une fois le runner local en place, plusieurs différences apparaissent dans les logs et le comportement des jobs.
Ce tableau les résume, puis chaque cas est détaillé ci-dessous.
Différences observables dans les jobs
Runner hébergé par GitLab Runner local
Cache distribué (bucket Google Cloud Storage), partagé entre machines Cache local au dossier de la machine, non partagé
Plusieurs jobs en parallèle (mise à l'échelle automatique) concurrent = 1 par défaut : un job à la fois
Images Docker pré-téléchargées sur l'infrastructure Images tirées depuis Docker Hub (limites de débit possibles)
VM et conteneurs jetables à chaque job Machine réutilisée : état résiduel à nettoyer
Version du runner mise à jour par GitLab Version du runner à mettre à jour manuellement
Linux (aussi Windows et macOS) Windows (Docker Desktop + WSL)

Cas 1 - Le cache des jobs
Le Runner local affiche dans les logs
No URL provided, cache will not be uploaded to shared cache server.

Le runner compresse et stocke les fichiers dans un dossier local de la machine (souvent monté via les volumes). Le cache n'est disponible que sur la machine qui l'a exécuté: si un autre développeur lance le pipeline, il repartira de zéro.
Runner hébergé par GitLab
Using presigned URL for cache upload
Uploading cache.zip to 
https://storage.googleapis.com/gitlab-com-runners-cache/project/40456472/a1/a1e0cc9ad92a17e9127fe8d43e87879fe0ec0ce8ac939948b9c2299d81accbb7
Les runners hébergés par GitLab sont connectés à un serveur de cache centralisé (un bucket Google Cloud Storage sécurisé). GitLab génère une URL pré-signée temporaire, c'est-à-dire une autorisation d'accès limitée dans le temps.
Ce cache distribué est partagé entre les runners hébergés par GitLab et persiste 14 jours sans mise à jour, pour une taille maximale de 5 Go par archive.

Cas 2 - Identifier le runner utilisé
À côté du job, GitLab indique quel type de runner a été utilisé. C'est le moyen le plus rapide de savoir si un job est parti sur un runner hébergé ou sur votre runner local.
Runner local
Running with gitlab-runner 19.1.1 (24b9b726)
  on local-docker CCQZhsWBW, system ID: s_dc447977ae38
  feature flags: FF_NETWORK_PER_BUILD:true

Preparing the "docker" executor
Duration: 39 seconds
Finished: 2 weeks ago
Queued:   0 seconds
Timeout:  1h (from project)
Runner:   #54252504 (CCQZhsWB) local-docker
Source:   Push
Runner hébergé par GitLab
Running with gitlab-runner 19.4.0~pre.1956.g7b010e09 (7b010e09) on k8s.saas-linux-small-amd64.runners-manager.gitlab.com/default nezyxEJex, system ID: r_GmKonCJ7bhV6
UUID: 019fd6c6-56c4-78a2-8961-bbb53e204387

feature flags: FF_USE_GIT_PROACTIVE_AUTH:true, FF_HASH_CACHE_KEYS:true, FF_MACHINE_OPTIONS_EXPAND_ENV:true
Preparing the "docker+machine" executor
Duration: 1 minute 2 seconds
Finished: 2 days ago
Queued:   0 seconds
Timeout:  1h (from project)
Runner:   #54907241 (nezyxEJe) k8s.saas-linux-small-amd64.runners-manager.gitlab.com/default
Source:   Push
Un nom court comme local-docker et l'exécuteur docker indiquent le runner local.
Un nom en *.runners-manager.gitlab.com et l'exécuteur docker+machine indiquent un runner hébergé par GitLab.

Cas 3 - Docker Desktop indisponible
Si Docker Desktop est fermé ou indisponible, le runner local ne peut pas démarrer le conteneur : le job passe en failed ou en Warning.
Dans ce cas, ouvrez Docker Desktop puis relancez le job ou la MR.
Running with gitlab-runner 19.1.1 (24b9b726)
  on local-docker CCQZhsWBW, system ID: s_dc447977ae38
  feature flags: FF_NETWORK_PER_BUILD:true
Preparing the "docker" executor
ERROR: Failed to remove network for build
ERROR: Preparation failed: getting docker info: 
error during connect: this error may indicate that the docker daemon is not running:
       Get "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.51/info": open //./pipe/docker_engine:
       Le fichier spécifié est introuvable. (docker.go:1287:0s)
Will be retried in 3s ...
... 
Timeout:  1h (from project)
Runner:   #54252504 (CCQZhsWB) local-docker
Commit    9cba4cac  in !364
update renovate image version

Pipeline #2847872547    Warning
 for fix/case-auto-promote 

Cas 4 - Concurrence des jobs
Runner local
La configuration par défaut est concurrent = 1: un seul job s'exécute à la fois sur la machine. Les jobs suivants restent en attente, même si le processeur et la mémoire sont disponibles.
Runner hébergé par GitLab
L'infrastructure est mise à l'échelle automatiquement: plusieurs jobs peuvent partir en parallèle, chacun sur une VM dédiée. C'est l'un des principaux écarts de comportement lorsque plusieurs pipelines sont lancés en même temps.
Pour autoriser plusieurs jobs simultanés en local, augmentez la valeur de concurrent dans le fichier config.toml, en gardant à l'esprit que chaque job consomme les ressources propres de votre machine.

Cas 5: Images Docker et limites de débit
Le runner local tire ses images depuis Docker Hub à chaque exécution, ce qui peut se heurter aux limites de débit de Docker Hub. Les runners hébergés par GitLab disposent d'images pré-téléchargées sur leur infrastructure, donc généralement plus rapides au démarrage.

Cas 6: État résiduel et nettoyage
Les runners hébergés par GitLab exécutent chaque job sur une VM neuve : rien ne subsiste d'un job à l'autre. Le runner local, lui, réutilise la même machine : images, volumes et caches s'accumulent dans le temps et peuvent saturer le disque. Un nettoyage périodique (images inutilisées, caches anciens) est donc recommandé.

Fonctionnement du runner
Un GitLab Runner est un agent léger qui fonctionne en continu pour exécuter les tâches (jobs) des pipelines CI/CD définis dans le fichier .gitlab-ci.yml
Il interroge le serveur GitLab via des connexions sortantes
↓
Lance les scripts demandés dans un environnement isolé
↓
Puis renvoie les résultats et les journaux (logs) en temps réel
Flux complet entre GitLab, le GitLab Runner et Docker Desktop
+-------------------------------------------------------------------------+
| [GitLab Cloud]                                                          |
|   Code Push  -->  Pipeline CI/CD  -->  [ File d'attente des Jobs ]      |
+-------------------------------------------------------------|-----------+
                                                              |
                                      (1) Demande de Job      | (2) Envoi du Job
                                      (Long Polling)          v
+-------------------------------------------------------------------------+
| [Machine Locale]                                                        |
|   +-----------------------+              +---------------------------+  |
|   | [ GitLab Runner ]     |              | [ Docker Desktop ]        |  |
|   |                       |              |                           |  |
|   |  Communication avec GitLab           |  Docker Engine / Daemon   |  |
|   |   / long polling      |                         |                |  |
|   |         |             |              |          v                |  |
|   |         v             |  (3) Ordre   | [ Conteneur Éphémère ]    |  |
|   |  Exécuteur Docker     +--------------> (Exécute le script,       |  |
|   |                       |              |   puis est détruit)       |  |
|   +-----------------------+              +---------------------------+  |
+-------------------------------------------------------------------------+

Cheat sheet des commandes principales
Depuis le dossier d'installation : C:\GitLab-Runner
Arrêter le service runner :
.\gitlab-runner stop
Démarrer le service runner :
.\gitlab-runner start
Vérifier si les runners peuvent se connecter à GitLab :
.\gitlab-runner verify
ou depuis n'importe quel emplacement :
Stop-Service gitlab-runner
Start-Service gitlab-runner
Afficher l'état du service runner :
.\gitlab-runner status
Désinscrire un runner par son nom :
gitlab-runner unregister --name {{name}}
Redémarrer le service runner :
.\gitlab-runner restart

Débogage en direct d'un job
Cette commande permet d'exécuter le runner en mode verbeux :
Exécutez la commande :
.\gitlab-runner.exe --debug run
puis faites tourner le job pour le déboguer.

On voit alors en direct ce que le pipeline exécute. C'est particulièrement utile lorsque les logs GitLab ne suffisent pas à comprendre pourquoi un job échoue.

Dans l'article suivant, nous commencerons par créer l'arborescence GitLab ainsi que le premier pipeline pour la branche develop, et tout ce qu'elle implique.

Laissez-moi un commentaire

En postant un commentaire anonyme, vous adhérez automatiquement aux conditions d'utilisation du site.