TP : Conteneurisation de votre application Node.js et intégration dans GitLab CI¶
Ce TP a pour objectif de vous faire pratiquer la création d'images Docker pour une application Node.js et l'automatisation de sa construction dans GitLab CI
Objectifs du TP¶
- Rédiger un Dockerfile pour une application Node.js
- Optimiser une image Docker avec le multi-stage build
- Comprendre et utiliser le Docker-in-Docker (DinD) ou Kaniko dans GitLab CI
- Automatiser la création de l'image Docker dans le pipeline CI
Étape 1 : Création du Dockerfile basique¶
Nous allons créer une image Docker pour l'application Node.js développée au TP précédent
- À la racine de votre projet, créez un fichier nommé
Dockerfile - Utilisez l'image de base
node:20-alpine(plus légère que l'image node standard) - Définissez le répertoire de travail dans le conteneur avec
WORKDIR(par exemple/usr/src/app) - Copiez les fichiers
package.jsonetpackage-lock.jsonouyarn.lock - Exécutez la commande d'installation des dépendances avec
RUN npm ci - Copiez le reste de votre code source dans le conteneur
- Exposez le port 3000 utilisé par votre application avec
EXPOSE - Définissez la commande de démarrage de votre application avec
CMD - N'oubliez pas d'ajouter un fichier
.dockerignorecontenantnode_moduleset.gitpour ne pas alourdir le contexte de build
Étape 2 : Test de l'image localement (Optionnel)¶
Si vous disposez de Docker sur votre machine, vous pouvez vérifier que l'image se construit correctement avant de l'envoyer sur GitLab
- Construisez votre image en lui donnant un nom avec la commande
docker build -t mon-app-node . - Lancez un conteneur à partir de cette image avec
docker run -p 3000:3000 mon-app-node - Vérifiez dans votre navigateur que l'application répond sur
http://localhost:3000
Étape 3 : Optimisation avec le Multi-stage Build¶
Pour avoir une image de production la plus légère possible, nous allons séparer l'étape de build de l'étape d'exécution
- Modifiez votre
Dockerfilepour introduire une première étape nomméebuilder(ex:FROM node:20-alpine as builder) - Dans cette étape
builder, installez toutes les dépendances et générez les fichiers nécessaires au bon fonctionnement de votre application - Créez une seconde étape en utilisant à nouveau
node:20-alpine - Définissez la variable d'environnement
NODE_ENVàproduction - Utilisez l'instruction
COPY --from=builderpour ne récupérer que le code compilé et les dossiers nécessaires depuis l'étape précédente - Observez la réduction de taille de l'image finale si vous la buildez localement
Étape 4 : Automatisation de la construction de l'image sur GitLab CI¶
Maintenant que le Dockerfile est prêt, nous allons demander à GitLab CI de construire notre image Docker à chaque modification du code
Nous utiliserons la méthode Kaniko qui est plus sécurisée et recommandée pour les environnements Kubernetes
- Dans votre fichier
.gitlab-ci.yml, ajoutez une étapebuild_image(ou similaire) à vos stages existants - Créez un job
build_docker_imagerattaché à cette nouvelle étape - Utilisez l'image
gcr.io/kaniko-project/executor:debugpour ce job avec l'entrypoint vide[""] - Dans la section script, ajoutez la commande pour configurer l'authentification au registre GitLab via un
echovers/kaniko/.docker/config.json - Lancez l'exécutable Kaniko pour construire l'image en lui fournissant le chemin du Dockerfile (
$CI_PROJECT_DIR/Dockerfile), le contexte ($CI_PROJECT_DIR) et la destination (par exemple$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA) - Commitez vos changements et vérifiez dans l'interface GitLab que le pipeline réussit et que l'image est bien poussée dans le Container Registry de votre projet
Étape 5 : Bonus - Utilisation de Docker-in-Docker (DinD)¶
Pour comprendre les différentes approches, vous pouvez essayer de configurer un autre job qui utilise DinD plutôt que Kaniko
- Créez un job
build_dinddans.gitlab-ci.yml - Utilisez l'image
docker:latestet déclarez le servicedocker:dind - Définissez la variable
DOCKER_HOSTàtcp://docker:2375 - Dans le script, connectez-vous au registre GitLab avec la commande
docker login(utilisez les variables$CI_REGISTRY,$CI_REGISTRY_USER,$CI_REGISTRY_PASSWORD) - Utilisez
docker buildetdocker pushde manière classique - Comparez l'exécution de ce job avec celui utilisant Kaniko dans l'interface de GitLab CI