DOCKER · GITLAB · CI/CD · DEVOPS
Je t’explique comment j’utilise la registry Docker GitLab pour stocker et distribuer mes images en toute confidentialité, sans dépendre de Docker Hub, gratuitement, avec un pipeline CI/CD qui build et push automatiquement à chaque commit.
📋 Au programme
- Pourquoi utiliser la registry GitLab plutôt que Docker Hub
- Prérequis : compte GitLab, Docker, CLI
- Créer un repo GitLab avec la registry activée
- Écrire un Dockerfile minimal
- Build, tag et push de l’image vers registry.gitlab.com
- Automatiser avec .gitlab-ci.yml
- Utiliser l’image dans FROM, docker-compose et CI
- Gestion des tokens et des accès
- Rendre une image publique

Quand j’ai commencé à construire des images Docker pour mes projets clients, ma première réaction a été de pousser tout sur Docker Hub. Rapide, connu, universel. Mais ça ne tient pas longtemps en production : les images privées sont payantes au-delà d’une certaine limite, la visibilité par défaut est publique si on n’y fait pas attention, et Docker Hub a connu plusieurs incidents notables ces dernières années.
J’utilise GitLab pour mes repos, et GitLab embarque une registry Docker complète, gratuite, intégrée au CI/CD. Autant en profiter. Dans cet article, je te montre comment je procède de A à Z : création du repo, Dockerfile, commandes de build et push, pipeline automatique, et gestion des accès.
Réponse rapide
Pour publier une image Docker sur la registry GitLab : docker build -t registry.gitlab.com/[group]/[repo]/[image]:[tag] . puis docker push. En CI/CD, les variables CI_REGISTRY, CI_REGISTRY_USER et CI_REGISTRY_PASSWORD sont injectées automatiquement.
Pourquoi utiliser la registry GitLab plutôt que Docker Hub
Docker Hub reste la référence pour les images publiques officielles (Nginx, PostgreSQL, Node.js…). Mais pour tes propres images, les limites arrivent vite :
⚠ Images privées limitées sur Docker Hub Free
Le plan gratuit Docker Hub ne propose qu’un seul repo privé. Dès que tu as plusieurs projets, tu paies ou tu t’organises autrement.
⚠ Rate limiting sur les pulls anonymes
Docker Hub limite les pulls depuis des IPs non authentifiées à 100/6h. Sur un CI/CD ou un cluster, c’est rapidement bloquant.
🔴 Incident Docker Hub 2023
Docker Hub a supprimé des repos gratuits inactifs et rendu publics temporairement des repos privés lors d’une migration, un signal fort pour ne pas dépendre d’un seul service tiers.
La registry GitLab, c’est quoi ? C’est une registry Docker OCI-compatible intégrée directement dans chaque projet GitLab. Gratuite sur gitlab.com (dans les limites de stockage du compte), sans restriction de repos privés, et connectée nativement au CI/CD. Mes images restent dans le même endroit que mon code.
🔒
Privé par défaut
Tes images suivent la visibilité de ton projet GitLab. Pas d’accès public accidentel.
🆓
Gratuit sur gitlab.com
Repos privés illimités, registry incluse dans le plan Free (5 Go de stockage).
⚡
Intégration CI/CD native
Variables d’authentification injectées automatiquement dans chaque job, pas besoin de gérer des secrets manuellement.
🏗️
Self-hosted possible
Si tu héberges ta propre instance GitLab, ta registry tourne sur ta propre infra. Zéro dépendance externe.
Prérequis
✅ Ce qu’il te faut avant de commencer
Un compte GitLab (gitlab.com gratuit suffit)
Docker installé sur ton poste (
docker --version doit répondre)
Git configuré localement (
git config --global user.email)
Un Personal Access Token GitLab avec le scope
read_registry / write_registry pour les push manuels
Créer un repo GitLab avec la registry activée
Sur gitlab.com, crée un nouveau projet : New project > Create blank project. Donne-lui un nom (ex: mon-app), choisis le niveau de visibilité (Private pour les projets clients), et valide.
La registry Docker est activée par défaut sur chaque projet. Tu peux la trouver dans le menu latéral : Deploy > Container Registry. L’URL de ta registry suivra ce format :
registry.gitlab.com/[namespace]/[projet]
Par exemple, si ton namespace GitLab est mon-groupe et ton projet mon-app :
registry.gitlab.com/mon-groupe/mon-app
Si la registry n’apparaît pas
Dans Settings > General > Visibility, project features, permissions, vérifie que Container Registry est activé. Sur une instance GitLab self-hosted, l’admin doit activer la registry au niveau de l’instance.
Écrire un Dockerfile minimal
Pour l’exemple, je pars sur une application Node.js simple. Le principe est identique pour Python, Go, PHP ou n’importe quel runtime.
# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
USER node
CMD ["node", "server.js"]
Bonnes pratiques Dockerfile
J’utilise systématiquement alpine pour réduire la surface d’attaque, USER node pour ne pas tourner en root, et npm ci --only=production pour éviter les dépendances de dev dans l’image finale.
Ajoute aussi un fichier .dockerignore pour ne pas copier les fichiers inutiles :
.git
node_modules
.env
*.md
tests/
coverage/
Build, tag et push vers registry.gitlab.com
La séquence est toujours la même : build, tag avec l’URL complète de la registry, login, push.
1. Authentification sur la registry
docker login registry.gitlab.com
GitLab te demande ton nom d’utilisateur et un token. N’utilise pas ton mot de passe GitLab – crée un Personal Access Token (Settings > Access Tokens) avec le scope write_registry.
Ne jamais utiliser ton mot de passe GitLab
Pour la registry, crée toujours un Personal Access Token ou un Deploy Token avec uniquement les scopes nécessaires. Le mot de passe principal ne doit jamais transiter dans des scripts ou des commandes shell.
2. Build de l’image avec le bon tag
docker build -t registry.gitlab.com/mon-groupe/mon-app:1.0.0 .
Je taggue toujours avec un numéro de version explicite. En plus, j’ajoute souvent :latest pour simplifier les déploiements :
docker build -t registry.gitlab.com/mon-groupe/mon-app:1.0.0 \
-t registry.gitlab.com/mon-groupe/mon-app:latest .
3. Push vers la registry GitLab
docker push registry.gitlab.com/mon-groupe/mon-app:1.0.0
docker push registry.gitlab.com/mon-groupe/mon-app:latest
Une fois poussée, tu retrouves l’image dans l’interface GitLab sous Deploy > Container Registry. Tu peux vérifier les layers, les tags, la date de push et la taille de chaque image.
Automatiser avec .gitlab-ci.yml
Le vrai gain de la registry GitLab, c’est l’intégration CI/CD. À chaque commit, le pipeline build l’image et la pousse automatiquement, sans que tu aies à gérer les credentials manuellement, car GitLab injecte les variables nécessaires dans chaque job.
# .gitlab-ci.yml
stages:
- build
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
IMAGE_LATEST: $CI_REGISTRY_IMAGE:latest
docker-build:
stage: build
image: docker:24
services:
- docker:24-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build -t $IMAGE_TAG -t $IMAGE_LATEST .
- docker push $IMAGE_TAG
- docker push $IMAGE_LATEST
only:
- main
- tags
Variables CI_REGISTRY_* : injectées automatiquement
CI_REGISTRY = URL de la registry du projet, CI_REGISTRY_USER = utilisateur de build, CI_REGISTRY_PASSWORD = token temporaire valide pour ce job. Ces trois variables sont disponibles dans tous les pipelines GitLab sans aucune configuration supplémentaire.
Optimiser avec le cache des layers
Pour accélérer les builds sur le CI, j’utilise le cache de layers Docker via BuildKit :
docker-build:
stage: build
image: docker:24
services:
- docker:24-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
DOCKER_BUILDKIT: "1"
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- |
docker build \
--cache-from $CI_REGISTRY_IMAGE:latest \
--build-arg BUILDKIT_INLINE_CACHE=1 \
-t $IMAGE_TAG \
-t $IMAGE_LATEST \
.
- docker push $IMAGE_TAG
- docker push $IMAGE_LATEST
only:
- main
- tags
Utiliser l’image dans FROM, docker-compose et CI
Dans un Dockerfile (FROM)
Pour construire une image qui hérite de ton image privée :
FROM registry.gitlab.com/mon-groupe/mon-app:1.0.0
# ... instructions supplémentaires
COPY config/ /app/config/
Dans un docker-compose.yml
version: "3.9"
services:
app:
image: registry.gitlab.com/mon-groupe/mon-app:latest
restart: unless-stopped
ports:
- "3000:3000"
environment:
NODE_ENV: production
env_file:
- .env
Sur le serveur de déploiement, tu devras te connecter à la registry avant de faire le docker compose pull :
docker login registry.gitlab.com -u [user] -p [token]
docker compose pull
docker compose up -d
Dans un autre pipeline GitLab
Si tu veux utiliser l’image d’un projet A dans le pipeline d’un projet B, tu peux utiliser un Deploy Token avec uniquement le scope read_registry :
# .gitlab-ci.yml du projet B
deploy:
stage: deploy
before_script:
- docker login registry.gitlab.com -u $DEPLOY_TOKEN_USER -p $DEPLOY_TOKEN_PASS
script:
- docker pull registry.gitlab.com/mon-groupe/mon-app:latest
- docker compose up -d
Conseil infogérance Linux-Man
J’utilise systématiquement des Deploy Tokens par projet client plutôt que des Personal Access Tokens. Ainsi, si un token est compromis, l’impact est limité au seul projet concerné, pas à l’ensemble du compte GitLab. Tu peux créer autant de Deploy Tokens que nécessaire dans Settings > Repository > Deploy tokens. Si tu veux déléguer la gestion des serveurs à une équipe externe, je propose un accompagnement dédié – contacte-moi.
Gestion des tokens et des accès
C’est souvent la partie qu’on bâcle au début et qu’on regrette plus tard. Voici comment je structure les accès selon les cas d’usage :
🔑 Personal Access Token (PAT)
Usage : push manuel depuis ton poste développeur. Scopes nécessaires : read_registry + write_registry. Crée-le dans User Settings > Access Tokens. Stocke-le dans ton keychain local, jamais en clair dans un script.
🚀 Variables CI/CD GitLab (CI_REGISTRY_*)
Usage : pipelines du projet lui-même. Variables injectées automatiquement par GitLab, aucune configuration nécessaire. Ces tokens sont éphémères (valables pour la durée du job uniquement).
🏭 Deploy Token
Usage : pull depuis un serveur de production, depuis un autre projet CI, ou depuis une application externe. Crée-le dans Settings > Repository > Deploy tokens. Scope read_registry uniquement si c’est juste pour pull. Stocke-le en variable CI/CD protégée ou dans un vault (HashiCorp Vault, Ansible Vault).
👥 Group-level access token
Usage : accès à plusieurs projets du même groupe. Pratique pour un pipeline de déploiement centralisé qui tire des images de plusieurs projets. Nécessite un plan payant sur gitlab.com.
Stocker le token de déploiement en variable CI/CD
Dans le projet qui doit puller l’image, va dans Settings > CI/CD > Variables et ajoute :
- DEPLOY_TOKEN_USER : le username du deploy token (ex:
gitlab+deploy-token-123) - DEPLOY_TOKEN_PASS : la valeur du token (marque-le Masked pour ne pas l’afficher dans les logs)
Ne jamais hard-coder un token dans le .gitlab-ci.yml
Le fichier .gitlab-ci.yml est commité dans le repo. N’y mets jamais de valeur de token en clair, utilise toujours des variables CI/CD GitLab, qui sont chiffrées au repos et masquées dans les logs.
Rendre une image publique : quand et comment
Par défaut, la registry GitLab suit la visibilité du repo : privé si le repo est privé, public si le repo est public. Dans certains cas, rendre une image publique a du sens.
Bons cas d’usage pour une image publique
- Un outil open source que tu veux partager librement
- Une image de base générique (ex : PHP + Composer + Node) réutilisable par d’autres
- Un projet communautaire ou un repo public GitLab servant de démo
- Simplifier le pull sans authentification dans des environnements tiers
Ne jamais rendre publique une image qui contient
- Des secrets ou variables d’environnement baked dans l’image
- Du code propriétaire client ou métier
- Des certificats ou clés privées copiés dans le filesystem
Rendre le repo GitLab public
La méthode la plus simple : passer le repo en public dans GitLab (Settings > General > Visibility). La registry devient automatiquement accessible en lecture sans authentification. N’importe qui peut alors faire :
docker pull registry.gitlab.com/votre-namespace/votre-repo:latest
Rendre uniquement la registry publique (repo privé)
GitLab permet aussi de garder le code source privé tout en exposant la registry publiquement. Dans Settings > Packages and registries > Container Registry, tu peux activer la visibilité publique de la registry indépendamment du repo.
Utile quand tu veux distribuer une image sans exposer le code source ni les pipelines CI/CD.
Utiliser Docker Hub pour les images vraiment publiques
Si l’image est destinée à une diffusion large (communauté open source, projet connu), Docker Hub reste la référence : meilleure indexation, pulls sans authentification sur toutes les plateformes, intégration native dans la doc officielle. Pour une image interne ou semi-publique, la registry GitLab suffit largement.
FAQ
Conclusion
La registry Docker GitLab est, selon moi, la solution la plus pragmatique pour qui utilise déjà GitLab. Pas de service tiers supplémentaire, pas de coût additionnel sur les plans usuels, et une intégration CI/CD qui élimine la gestion manuelle des credentials dans les pipelines.
Le flux que je recommande en production : Dockerfile minimal + utilisateur non-root + .gitlab-ci.yml avec cache de layers + cleanup policy activée + Deploy Tokens par environnement. C’est robuste, auditable et reproductible.
Si tu veux aller plus loin sur l’automatisation de ton infra Docker et GitLab CI, jette un oeil à mon article sur la gestion des variables et secrets GitLab CI et à comment je construis des images Docker PHP production.
Tu veux externaliser la gestion de ton infra Docker et GitLab ?
Je m’occupe de la mise en place, de la sécurisation et de la maintenance de tes pipelines CI/CD et de ton infra conteneurisée. Devis gratuit, réponse sous 24h.