Docker

C’est mon tout premier article, alors soyez indulgents 😅 — et surtout, n’hésitez pas à me dire ce que vous en pensez ! Vos retours me permettront de m’améliorer et de mieux répondre à vos attentes.

Depuis longtemps, l’idée de créer un blog dédié aux technologies émergentes et bien aussi celles par lesquelles j’ai travaillé me trotte dans la tête. J’ai souvent été freiné par des contraintes diverses, mais aujourd’hui, je franchis enfin le pas. Ce blog sera le reflet de mes expériences, de mes découvertes et de ma passion pour les outils qui façonnent le monde numérique.

Pour inaugurer cette aventure, j’ai choisi de me pencher dans un premier temps sur Docker, une technologie incontournable dans l’univers du DevOps et du déploiement applicatif. Dans ce premier article, nous allons explorer ensemble ce qu’est Docker, pourquoi il est devenu si populaire, et comment l’utiliser efficacement dans différents contextes — que ce soit pour le développement local, l’intégration continue ou le déploiement en production.

C’est quoi Docker !

Docker est une plateforme de conteneurisation reposant sur la technologie des Linux Containers (abrégée LCX). Elle a été conçue pour répondre à une problématique bien connue dans le monde du développement logiciel : le décalage entre les environnements du développeur et de l’utilisateur final (MOA). Cette friction se résume souvent par un échange devenu presque légendaire : L’utilisateur : "Ça ne fonctionne pas chez moi." Le développeur : "Pourtant, ça marche parfaitement sur mon ordinateur."

Grâce à Docker, cette disparité est atténuée en permettant d’exécuter les applications dans des environnements isolés, reproductibles et cohérents, quel que soit le système hôte.

En effet, Docker à procéder dans ce qu’on appelle l’isolation des environnements avec l’utilisation de ce qu’on appelle les conteneurs, afin d’encapsuler l’application ou le projet avec tout dont elle a besoin pour fonctionner (configuration, classes, dépendances, JDK utilisé dans un projet java, etc.).

Installation et travail avec Docker

pour travailler avec docker, il faut l’installer et bien évidemment préparer l’environnement pour qu’il répond aux exigences de docker, les points fondamentaux à prendre en considération sont :

  • La mise à jour de WSL (Windows Subsystem for Linux) : il faut obligatoirement passer de WSL1 à WSL2, en effet; le WSL1 c’est juste pour interprétation des commandes Linux sous le système d’exploitation Windows, alors que WSL2 met à notre disposition une vraie machine virtuelle VM avec un vrai noyau linux.

  • L’activation de la virtualisation matérielle : il faut vérifier si la virtualisation matérielle (hardware virtualization) est activée ou non (via gestionnaire des taches, rubrique des performances, consultation du processeur), si elle est désactivée il faut l’activer via le BIOS du le OS hôte.

  • L’installation de l’outil Docker Desktop dans votre système d’exploitation (Windows, Linux ou mac) et le lancer pour commencer à pratiquer.

Une fois ces étapes sont terminées, on vérifie que notre installation est bien terminée en exécutant la commande :

docker --version (ou docker -v)

dans la console de Docker Desktop ou simplement dans une CLI, ça normalement doit afficher le résultat suivant : Docker version 26.1.4, build 5650f9b.

Maintenant, on fera un deuxième teste, on va créer un conteneur à la base d’une image docker préexistante dans le registre Docker Hub(comme hello-world, ubuntu, nginx, etc) , Ainsi, on va exécuter la commande au syntaxe suivant : docker pull IMAGE_NAME:TAG

docker pull hello-world

docker dans ce cas va chercher cette image en local, s’elle ne la trouve pas il va chercher dans le Docker Registry Docker Hub et tirer l’image et la stocker dans son stockage interne. Et puis on va créer un conteneur docker à la base de cette image avec la commande au syntaxe: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

docker run -d -p 8000:8000 --name mon-conteneur hello-world

docker dans ce cas créer un conteneur via le docker daemon (ou Dockerd) qui est bien le moteur docker qui permet la manipulation et la gestion des images, conteneurs, volumes, réseaux , etc. Et pour les option de la commande docker run vous la trouvez ci-dessous :

  • l’argument -it : il lance le conteneur avec un terminal interactif c’est utile dans le cas d’un conteneur crée à la base d’une image docker comme ubuntu, en effet: il nous ouvre un terminal dans le conteneur pour exécuter notre commandes linux. donc it c’est pour interactif mode.

  • l’argument -d : c’est-à-dire lancer le conteneur en mode détaché, ou autrement dit le conteneur est démarré en arrière-plan.

  • l’argument —name : c’est pour donner un nom personnalisé au conteneur.

  • l’argument -v /chemin/local:/chemin/conteneur : monte un volume pour partager des fichiers entre la machine hôte et le conteneur.

  • l’argument —rm : c’est pour la suppression du conteneur une fois il est arrêté.

  • l’argument -p : c’est utilisé dans le cas où on veut que notre conteneur soit accessible via l’extérieur (navigateur, ou une autre application), ainsi p c’est pour publier un port vers l’extérieur.

quand notre conteneur est crée, on peut consulter ses logs via la commande suivante :

docker logs nom-conteneur

Fonctionnement de Docker !

comprendre le fonctionnement de docker en arrière-plan est crucial en guise de la maitrise de cette technologie qui joue un rôle primordial dans les processus CI/CD. Alors comme il est mentionné dans le début de ce Blog, Docker est une plateforme de conteneurisation. Mais c’est quoi la conteneurisation ?

La conteneurisation c’est le fait d’encapsuler ou bien d’empaqueter une application avec tous dont elle a besoin pour fonctionner entre autres :

  • le code source de l’application.

  • les bibliothèques (ou librairies) utilisées.

  • les dépendances et la configuration de l’application.

Ainsi, l’application peut tourner dans un environnement fiable, isolé et indépendant peu importe l’environnement.

Et un conteneur c’est une unité légère, portable (je peux l’exécuter sur n’importe quelle machine avec Docker installé) et autonome qui exécute une application.

NB: Il y a un outil qui est un conteneur aussi en lui même, qui s’appelle portainer, qui mets à notre disposition une interface graphique (GUI) intuitive et nous permet aussi de visualiser et de manipuler les images, les conteneurs et les volumes avec lesquelles on travaille. Vous trouvez ci-dessous deux images qui illustrent l’interface de ce conteneur et sa liaison avec Docker Desktop :

Liaison de Portainer avec Docker Desktop

Maintenant pour le fonctionnement de docker, c’est géré principalement le moteur docker (docker engine) qui s’appelle le docker daemon et se prononce docker démon, c’est un programme qui tourne en arrière-plan et gère le cycle de vie des conteneurs, les images, les réseaux, les volumes et les interactions avec les clients et les registres docker comme Nexus, Docker Hub, etc.

Le dockerd interagit avec les clients docker (interface en ligne de commande) via des APIs REST, à titre d’exemple , quand on tape docker —version, le client envoie cette commande au moteur dockerd via l’API REST de docker et ce dernier renvoie la réponse qui affichée dans notre prompt ligne de commande.

Dans l’image ci-dessous c’est la partie de configuration du dockerd dans le Docker Desktop :

Dans cette configuration de dockerd, on a activé le Garbage Collector qui responsable du nettoyage automatique des ressources inutilisées (images, cache de build, couches intermédiaires, etc.) et ici quand les artefacts de build dépasse la limite de stockage spécifiée (ici vaut 20GB), le GC procède à la suppression des éléments les moins récemment utilisés, ce qui en conséquence garde le système plus léger et sans supprimer les éléments utiles.

Et pour la ligne experimentale: false, c’est pour utiliser uniquement les fonctionnalités stables de docker.

Avant de passer à la pratique, je tiens à clarifier une nuance importante entre dockerd et containerd. En réalité, dockerd s’appuie sur containerd pour assurer la gestion et la manipulation des conteneurs, comme leur création, démarrage, arrêt ou suppression. En tant que runtime de bas niveau, containerd prend en charge le cycle de vie complet des conteneurs, ce qui en fait un composant essentiel dans l’architecture Docker.

Cas pratique simple !

Pour rentrer dans le vif du sujet, et lier la théorie avec la pratique on va créer une application web avec SpringBoot, simple et avec un circuit nominal, via intellij IDEA ou n’importe quel autre IDE. Dans un premier temps, on génère le projet avec un minimum de configuration, puis ajouter les dépendances nécessaires pour démarrer avec SpringBoot à savoir les starters, et aussi les dépendances de maven (cas échéant), et finalement une dépendance d’une base de données comme H2 qui est une base volatile (en mémoire, utile et pratique pour l’apprentissage et les testes), ensuite la mise en place d’un controlleur, service et repository (afin d’interagir avec la base de données via Spring Data JPA). Ensuite lancer l’application et tester notre API qu’on va mettre dans le controlleur.

Quand notre API marche bien, on va arrêter notre projet et essayer d’empaqueter (encapsuler) notre application et la conteneuriser pour la tester dans différentes machines et environnements et voir qu’elle va tourner bien et notre API va nous donner le résultat attendu.

Maintenant on va ajouter dans la racine de notre projet un fichier qui s’appelle le Dockerfile, qui est un élément central dans l’écosystème docker, il contient une série d’instructions (des mots clés que docker comprend et quand peut qualifier comme des directives docker, comme COPY, FROM, EXPOSE, ENTRYPOINT, WORKDIR, RUN), voilà un exemple concret du Dockerfile :

Explication de ce Dockerfile, le FROM c’est pour indiquer l’image de base sur laquelle on va créer notre image docker (cette image inclut tous ce qu’il faut pour compiler et exécuter des applications java 8), le WORKDIR crée un dossier dans notre image docker et puis COPY pour notre jar depuis le target/ vers le dossier crée dans l’image docker, ensuite EXPOSE signifie que l'application écoute sur le port 8000 à l'intérieur du conteneur, après dans le démarrage du conteneur avec docker run on spécifie si ce port va être accessible depuis l’extérieur ou non, en effet : docker run -p PORT_HOTE:PORT_CONTENEUR, donc si par exemple on fait docker run -p 8080:8000 ça veut dire que l’application va être accessible dans le réseau via le port 8080 de la machine ou du serveur où tourne Docker après c’est le dockerd qui fait le mapping des ports et redirige les requêtes reçues sur le port 8080 de l’hôte vers le port 8000 à l’intérieur du conteneur, là où l’application écoute.

Maintenant, une fois notre Dockerfile est bien construit, on fait une mvn clean package pour empaqueter notre application dans un jar qu’on trouve dans le dossier target/ de notre projet. Ensuite, on crée notre image docker avec la commande :

docker build -t nom-image:tag

si aucun tag n’est spécifié latest est pris par défaut, cette commande scanne et exécute le Dockerfile commande par commande et nous génère enfin l’image docker et la stocke dans son stockage interne (on peut lister les images crées avec la commande docker images), et puis on crée notre conteneur à la base de cette image docker, commande déjà spécifiée en haut mais je la rappelle ici : docker run [OPTIONS] IMAGE [COMMAND] [ARG...].

Ainsi on peut exécuter ce conteneur depuis n’importe quelle machine, à condition d’avoir docker installée dedans et tester notre API sans problème.

Remarque : on peut utiliser le Dockerfile pour générer les images docker des applications java, mais aussi on peut utiliser un autre fichier qui s’appelle le docker-compose avec l’extension yaml. Sauf que ce dernier est utilisé pour l’exécution de plusieurs conteneurs ensemble, et tout dépends de la manière de la gestion des services dans le docker-compose.yml est faite. Il est lancé par la commande docker-compose up.

Conclusion

Docker s’impose aujourd’hui comme une pierre angulaire dans les pratiques modernes de développement, de déploiement et de livraison continue. Grâce à sa capacité à encapsuler les applications dans des conteneurs légers, portables et reproductibles, il facilite non seulement la cohérence entre les environnements de développement et de production, mais aussi l’automatisation des workflows.

Associé à des outils comme Jenkins, Docker permet de construire des pipelines CI/CD robustes, agiles et évolutifs, réduisant les délais de mise en production tout en améliorant la qualité du code. Cette synergie entre conteneurisation et intégration continue transforme profondément la manière dont les équipes collaborent, testent et livrent leurs applications.

Dans un monde où la rapidité, la fiabilité et la scalabilité sont des exigences incontournables, Docker représente bien plus qu’un simple outil : c’est un catalyseur de transformation numérique, un levier d’innovation, et un allié incontournable pour toute organisation souhaitant adopter une approche DevOps efficace et durable.

2
Subscribe to my newsletter

Read articles from Abdelbadia OULABACH directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Abdelbadia OULABACH
Abdelbadia OULABACH

Je me nomme Abdelbadia OULABACH, mais vous pouvez tout simplement m’appeler Abdel. Je suis Technical Leader et Ingénieur Développeur au sein de la Société Royale d’Encouragement du Cheval (SOREC). Animé par une curiosité constante et un profond intérêt pour les technologies émergentes, je m’efforce de rester à l’avant-garde des tendances du monde numérique. Ma démarche ne se limite pas à l’utilisation des outils technologiques : je cherche à en comprendre les fondements, les mécanismes internes et le fonctionnement du noyau, afin d’appréhender pleinement ce qui se joue "sous le capot". C’est dans cette optique que j’ai entrepris une exploration personnelle à travers la lecture d’articles spécialisés, de blogs et d’ouvrages techniques. Mon objectif : extraire l’essence de ces savoirs, les confronter à mon expérience terrain, et les retranscrire à travers des billets de blog, dans une volonté de partage et de transmission.