Images, conteneurs et volumes : le modèle mental en 30 minutes
Image, conteneur, volume et réseau : les quatre objets de Docker, manipulés avec une vraie base PostgreSQL dont les données survivent au conteneur.
Module 0 · Démarrer vite et sereinement
Objectif du chapitre
Vous savez expliquer et manipuler les quatre objets de Docker : image, conteneur, volume et réseau. Vous lancez PostgreSQL dans un conteneur, le supprimez et retrouvez vos données. Durée : 30 min · 80 % pratique.
Prérequis : Installer Docker et vérifier son poste (chapitre 01) : tag dk01 posé.
Comment lire le schéma
- À gauche, l’image : une pile de couches en lecture seule (jaune). Chaque instruction du Dockerfile en ajoute une.
- Au centre, deux conteneurs lancés depuis la même image. Chacun reçoit sa propre couche d’écriture (vert) : ce qu’il modifie reste chez lui et disparaît avec lui.
- À droite, le volume (violet) vit en dehors des conteneurs. C’est là que vont les données à garder (base de données, fichiers envoyés).
Le modèle mental en quatre phrases
- Une image est un modèle en lecture seule, fait de couches empilées. Elle se construit avec un Dockerfile et se partage via un registre.
- Un conteneur est une image en cours d’exécution, plus une fine couche d’écriture. Il est jetable : le supprimer efface tout ce qui a été écrit dedans.
- Un volume est un espace de stockage géré par Docker, monté dans un conteneur. Il survit à la suppression du conteneur.
- Un réseau relie des conteneurs entre eux : sur un réseau commun, ils se joignent par leur nom.
C’est la réponse au défi du chapitre 01 : votre fichier était dans la couche d’écriture du conteneur, supprimée avec lui.
Étape 1 : explorer une image
docker pull node:22-alpine
docker image ls node
docker image history node:22-alpine # les couches et leur taille
docker image inspect node:22-alpine --format '{{.Architecture}} {{.Config.User}}'
Notez la taille : environ 150 Mo pour Node sur Alpine, contre plus de 1 Go pour node:22. Cette différence pèsera sur chaque build et chaque déploiement de MonTour.
Les couches : ce qu’est vraiment une image
Une image n’est pas un gros fichier. C’est une pile de couches en lecture seule, chacune contenant uniquement les fichiers ajoutés, modifiés ou supprimés par une instruction du Dockerfile. Quand un conteneur démarre, Docker pose par-dessus une couche d’écriture vide, et Linux (pilote overlay2) présente l’ensemble comme un seul disque.
Comment lire le schéma
- Lisez de bas en haut : chaque instruction ajoute une couche par-dessus la précédente. La taille indique ce que la couche ajoute.
- La couche rouge (
npm ci) est la plus lourde : on veut la reconstruire le moins souvent possible. - En vert, la couche d’écriture du conteneur, ajoutée au lancement. Linux superpose le tout (overlay2) : le conteneur voit un seul système de fichiers.
- C’est pourquoi on copie
package*.jsonavant le reste du code : modifier une page ne relance pasnpm ci.
- Partage : dix images basées sur
node:22-alpinene stockent cette base qu’une fois.docker system df -vmontre l’espace partagé. - Copie à l’écriture : si un conteneur modifie un fichier d’une couche de l’image, ce fichier est d’abord copié dans sa couche d’écriture. L’image ne change jamais.
- Supprimer ne libère rien : un
RUN rmdans une couche ultérieure cache le fichier, mais il reste dans la couche où il a été ajouté, donc dans l’image (et il fuit si c’était un secret). - Cache de build : Docker réutilise une couche tant que l’instruction et ses fichiers d’entrée n’ont pas changé. Dès qu’une couche change, toutes les suivantes sont reconstruites.
Lab : voir les couches de vos propres yeux
docker pull node:22-alpine
docker history node:22-alpine # une ligne par couche, avec sa taille
docker image inspect node:22-alpine --format '{{json .RootFS.Layers}}' | tr ',' '\n' | wc -l
docker image inspect node:22-alpine --format '{{json .GraphDriver.Data}}' # LowerDir, UpperDir, MergedDir
# Copie à l'écriture : ce qu'un conteneur change
docker run -d --name essai node:22-alpine sleep 600
docker exec essai sh -c 'echo test > /tmp/a.txt && rm /usr/local/bin/npx'
docker diff essai # A = ajouté, C = changé, D = supprimé
docker rm -f essai
# Espace partagé entre images
docker system df -v | head -20
| Ce que vous observez | Pourquoi |
|---|---|
docker history montre des couches de 0 o (ENV, WORKDIR, CMD) | Ces instructions ne changent que les métadonnées, pas les fichiers |
docker diff affiche A /tmp/a.txt et D /usr/local/bin/npx | Les changements sont dans la couche d’écriture du conteneur, l’image est intacte |
Dans un nouveau conteneur, npx est de nouveau là | La couche d’écriture a disparu avec le conteneur supprimé |
La colonne SHARED SIZE de docker system df -v n’est pas nulle | Les images de même base partagent leurs couches sur le disque |
Pour aller plus loin
L’outil dive (docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive node:22-alpine) explore une image couche par couche et repère l’espace gaspillé. Les chapitres « Build multi-étapes » et « Cache de build » s’appuient directement sur ce modèle.
Étape 2 : le cycle de vie d’un conteneur
docker run -d --name essai node:22-alpine sleep 600
docker ps # il tourne
docker exec -it essai sh # entrer dedans, puis : node -v ; exit
docker stop essai && docker ps -a # arrêté, mais toujours là
docker rm essai # supprimé, couche d'écriture comprise
Pratique : PostgreSQL et un volume
Lancez une base avec un volume nommé, créez une table, supprimez le conteneur, relancez-en un nouveau sur le même volume : la table est toujours là.
docker volume create pgdata
docker run -d --name pg -e POSTGRES_PASSWORD=dev -v pgdata:/var/lib/postgresql/data postgres:17-alpine
docker exec -it pg psql -U postgres -c "create table tickets(id serial primary key, numero int);"
docker rm -f pg
docker run -d --name pg -e POSTGRES_PASSWORD=dev -v pgdata:/var/lib/postgresql/data postgres:17-alpine
docker exec -it pg psql -U postgres -c "\dt" # la table tickets est là
Étape 3 : relier deux conteneurs par un réseau
docker network create montour_net
docker network connect montour_net pg
docker run --rm -it --network montour_net postgres:17-alpine \
psql -h pg -U postgres -c "select 1" # "pg" est résolu par son nom
Aucun port n’a été publié sur votre machine : la base n’est joignable que depuis le réseau montour_net. C’est exactement ce que vous ferez en production.
Réflexe sécurité
-p 5432:5432 publie la base sur toutes les interfaces de la machine, y compris le Wi-Fi d’un café ou l’IP publique d’un VPS. Docker contourne même certains pare-feu comme ufw. Publiez un port uniquement quand c’est nécessaire, et limitez-le à 127.0.0.1:5432:5432.
Étape 4 : faire le ménage
docker rm -f pg
docker network rm montour_net
docker volume rm pgdata
docker system df # ce que Docker occupe sur le disque
docker system prune # supprime ce qui est arrêté et inutilisé (lisez la question)
Le prompt reproductible
Même point de départ, même contexte, même résultat : partez du tag indiqué et collez ce prompt tel quel.
Point de départ : tag dk01 du dépôt MonTour.
Rôle : tu es un formateur Docker. Tu poses des questions, tu ne donnes
pas les réponses.
Tâche : pose-moi 5 questions courtes pour vérifier que je distingue image,
conteneur, volume et réseau, avec un exemple tiré de MonTour (base PostgreSQL,
application Next.js). Attends ma réponse à chaque question avant la suivante,
puis corrige en une ligne.
Contraintes : n'exécute aucune commande.
Qualité et sécurité : ce que vous vérifiez
- Les données ne vivent jamais dans un conteneur : toujours un volume nommé pour une base.
- Des tags précis :
postgres:17-alpine, paspostgres:latest, pour que la même commande donne le même résultat dans six mois. - Le minimum de ports publiés, et sur
127.0.0.1quand c’est local. - Sans IA : expliquez à voix haute ce que fait chaque option de la commande
docker runde la base.
Outillage IA de ce chapitre
Connecteurs MCP : aucun.
Agents : aucun. L’assistant joue ici le rôle de formateur : il interroge, vous répondez.
Vérifier
- ☐ Vous expliquez la différence entre image et conteneur en une phrase.
- ☐ La table
ticketsa survécu à la suppression du conteneur grâce au volume. - ☐ Deux conteneurs se sont joints par leur nom sur
montour_net. - ☐
docker ps -aetdocker volume lssont propres après le ménage. - ☐ Commit et tag
dk02posés (vos commandes dansdocs/docker-memo.md).
Défi
Lancez deux conteneurs PostgreSQL sur le même volume en même temps. Que se passe-t-il, et pourquoi est-ce une très mauvaise idée en production ?
Pour aller plus loin
Suivez votre progression. Créez un compte gratuit pour cocher vos leçons et reprendre là où vous en étiez.
Créer un compte gratuit