Que signifie vraiment « Un menu hamburger, s’il vous plaît » ?
La dernière fois, nous avons utilisé un Dockerfile pour créer notre propre « image Docker (Image) ». C’est comme une « recette qui ne change jamais », où l’ordre pour poser le steak sur le pain puis ajouter la laitue est écrit une fois pour toutes.
Il est maintenant temps d’utiliser cette recette pour lancer le vrai commerce, autrement dit le service. Mais dès qu’on commence à utiliser Docker, des termes déroutants apparaissent. Container, Service, Stack… tout semble se ressembler. Alors, quelle est exactement la différence ?
Si on ne maîtrise pas ces concepts, on finit plus tard par se perdre en écrivant des scripts de déploiement, en se demandant : « Pourquoi ai-je démarré le conteneur, mais le service ne monte toujours pas ? » Pour remettre aujourd’hui de l’ordre dans cette généalogie, j’ai apporté la langue universelle du monde entier : l’analogie du restaurant de hamburgers.

1. Conteneur (Container) : le hamburger préparé après la commande
- Définition : l’« entité concrète » obtenue en exécutant une image et en la chargeant en mémoire.
- Caractéristique : on ne peut pas tendre au client la feuille de recette (l’image). Il faut lui servir un « hamburger (conteneur) » tout chaud, préparé selon la recette.
- Commande :
docker run my-burger
Si je lance une instance de serveur, cela signifie que j’ai exécuté « un conteneur ».
2. Service (Service) : la gestion du stock pour le même menu
L’heure du déjeuner arrive et les clients affluent. Avec la cadence d’un hamburger à la fois, il est impossible de suivre. Nous décidons donc d’augmenter l’équipe en cuisine et de préparer à l’avance trois « cheeseburgers ». À partir de là, je ne gère plus seulement « un cheeseburger », mais toute la « ligne de cheeseburgers », c’est-à-dire le Service.
- Définition : un « ensemble de conteneurs » créés à partir de la même image.
- Caractéristique : on peut lui attribuer des « règles » comme « Garde toujours 3 exemplaires de ce menu en stock (Replicas=3) ». Si un hamburger tombe par terre (erreur), il en prépare automatiquement un nouveau.
- Objectif : le « Scale-out », c’est-à-dire la montée en charge horizontale. Répartition du trafic et stabilité.
3. Stack : la formule, autrement dit le package complet
Un hamburger seul ne suffit pas. Il faut aussi des frites, la DB, et un cola, Redis. Ce n’est que lorsque tout cela est réuni qu’on obtient enfin « un repas complet », c’est-à-dire l’application.
- Définition : le « groupe de plus haut niveau » qui réunit des services différents (web, DB, cache).
- Caractéristique : un hamburger et un cola se mangent plus facilement quand ils sont sur le même plateau (connexion réseau). Une fois regroupés dans un stack, ils disposent d’un espace dédié (Network) pour communiquer entre eux.
Le problème : rien que passer la commande va me couper le souffle
Le concept est clair, mais dès qu’il faut l’exploiter pour de vrai, cela devient vite un casse-tête. Le service web, autrement dit le stack, que nous voulons construire a généralement besoin des composants suivants.
- Spring Boot (burger) : 2 menus principaux (redondance)
- PostgreSQL (frites) : 1 accompagnement
- Redis (cola) : 1 boisson
Lancer tout cela avec des commandes Docker brutes, docker run, revient à passer une commande au comptoir de cette façon.
« Bonjour, je voudrais un “cheeseburger (Spring)”, avec le steak cuit à point plus, sans cornichons et avec beaucoup de sauce. Ah, et aussi des “frites (DB)”, mais sans sel, avec trois sachets de ketchup. Enfin, pour le “cola (Redis)”, je le veux en version zéro avec seulement la moitié de la glace. Et merci de mettre ces trois éléments sur “un seul plateau (Network)”. »
# En realite il faut taper ces commandes a chaque fois
$ docker run -d --name my-web -e PATTY=medium -e PICKLE=no -p 8080:8080 ...
$ docker run -d --name my-db -e SALT=no ...
$ docker run -d --name my-redis -e ICE=half ...
Peut-on vraiment réciter cette longue commande sans faute à chaque déploiement ? Et si l’ordre est inversé et que les frites arrivent après le hamburger ? Le client, c’est-à-dire l’utilisateur, ne sera pas content.
Le sauveur : Docker Compose – « Comme d’habitude, s’il vous plaît ! »
C’est pourquoi les développeurs ont réfléchi : « Et si on écrivait à l’avance cette commande compliquée sur un “menu, document”, pour pouvoir simplement dire : “Donnez-moi la formule numéro 1” ? »
C’est ainsi qu’est né « Docker Compose ». Si nous définissons notre propre « formule personnalisée » dans un fichier nommé docker-compose.yml, Docker se charge d’envoyer la commande en cuisine et de tout disposer proprement sur le plateau.

[Action] Créer sa propre formule
Ne restons pas dans la théorie. Faisons démarrer en une seule fois le serveur Spring et la DB présents en local. Il suffit de créer un fichier docker-compose.yml à la racine du projet et d’y coller le contenu ci-dessous.
version: '3.8'
services:
# 1. Frites (DB)
my-database:
image: postgres:14
environment:
POSTGRES_PASSWORD: mysecretpassword
ports:
- "5432:5432"
# 2. Cheeseburger (Web)
my-web-server:
image: my-spring-app:latest
ports:
- "8080:8080"
depends_on:
- my-database # "Les frites doivent etre pretes avant que le burger ne sorte" (ordre garanti)
environment:
DB_URL: jdbc:postgresql://my-database:5432/mydb
Ensuite, on prononce la formule magique dans le terminal.
# "Un menu 1 (docker-compose.yml), s il vous plait !"
$ docker-compose up -d
Résultat : Docker lit ce fichier de menu, démarre d’abord la DB, puis lance le serveur Spring dès que la DB est prête. C’est précisément le point de départ du concept IaC, Infrastructure as Code, c’est-à-dire gérer l’infrastructure avec du code. Désormais, même une configuration serveur complexe se partage au moyen d’un seul « fichier de menu ».
Pour conclure : Works on My Machine? Works on ANY Machine!
L’excuse qui ouvrait cette série, « Mais ça marche sur ma machine… », ne tient plus. Nous avons compris Linux, l’OS, isolé les environnements avec Docker, le Container, et défini des services complexes dans un seul fichier avec Docker Compose.
Désormais, tant que j’ai le fichier docker-compose.yml que j’ai écrit, je peux servir exactement le même menu hamburger sur mon ordinateur, sur celui de mon responsable ou sur un serveur AWS, en une minute.
Nous ne sommes plus de « simples codeurs ». Nous sommes devenus des « ingénieurs » capables de concevoir non seulement le code que nous écrivons, mais aussi le monde, l’environnement, dans lequel ce code va tourner. Ainsi s’achève la série [Works on My Machine].
À partir de la prochaine série, nous partirons vers le monde de [The Pipeline : automatisation CI/CD], où nous confierons le pénible processus de déploiement aux machines sur la base de cette infrastructure solide.


