Docker pour débuter : images, conteneurs et volumes

Docker pour débuter tient en trois notions. Une image est un modèle figé qui embarque une application et tout ce qu’elle requiert. Un conteneur est une instance de cette image, lancée comme un processus isolé. Un volume garde les données hors du conteneur, que vous pouvez alors supprimer puis recréer sans rien perdre.
La documentation officielle (docs.docker.com) précise que Docker, écrit en Go, isole chaque processus grâce aux espaces de noms du noyau Linux. Le client docker transmet les ordres au démon dockerd, qui construit, lance et distribue les conteneurs.
Conteneur ou machine virtuelle : ce qui change vraiment
Une machine virtuelle embarque un système d’exploitation entier, avec son propre noyau et ses pilotes. Un conteneur Docker se contente d’un processus isolé et des fichiers dont il a besoin. Tous les conteneurs d’une machine partagent son noyau, ce qui fait tourner davantage d’applications sur le même matériel.
La documentation de Docker lui prête quatre traits :
- autonome, car il embarque ses dépendances ;
- isolé, avec peu d’influence sur l’hôte et ses voisins ;
- indépendant, puisque supprimer un conteneur laisse les autres intacts ;
- portable, du poste de développement au centre de données.
Ce dernier point règle le vieux « ça marche chez moi » : interpréteur, bibliothèques et configuration voyagent avec l’application.
Images, couches et registre : d’où vient un conteneur
Une image se lit en couches
Une image Docker rassemble fichiers, binaires, bibliothèques et configuration. Elle est immuable : une fois construite, elle ne change plus, seule une nouvelle image peut l’étendre. Elle se compose de couches, chacune décrivant des fichiers ajoutés, modifiés ou supprimés. Au lancement, Docker empile ces couches et pose au sommet un répertoire inscriptible propre au conteneur. Plusieurs conteneurs tournent donc depuis la même image, qui reste intacte. La commande docker image history nginx:alpine affiche cet empilement.
Le registre, entrepôt des images
Un registre stocke et partage les images ; un dépôt y regroupe les versions d’une même image. Docker Hub est le registre public interrogé par défaut, et ses Docker Official Images forment un point de départ fiable.
docker pull postgres:17
docker push mon-compte/mon-api:1.0
Un tag comme :17 reste réattribuable par l’éditeur. Épingler l’image par son condensat (digest) fige exactement la même version.

Docker pour débuter : du premier conteneur à sa suppression
Sur Linux, Docker Engine s’installe sur Debian, Ubuntu, Fedora ou RHEL. Sous Windows et macOS, il passe par Docker Desktop, dont l’usage commercial exige un abonnement payant au-delà de 250 salariés ou de 10 millions de dollars de chiffre d’affaires annuel, selon la page d’installation. Pour apprendre Docker, le test sudo docker run hello-world suffit : il télécharge une image, la lance, affiche un message puis s’arrête.
Le groupe docker dispense de taper sudo, mais la documentation prévient qu’il confère des privilèges équivalents à root. Il se réserve donc aux administrateurs, comme les droits décrits dans les commandes Linux d’administration.
Le cycle de vie tient ensuite en quelques commandes :
docker create --name web -p 8080:80 nginx:alpine
docker start web
docker ps -a
docker stop web
docker rm web
docker create prépare le conteneur avec le statut created, sans le lancer, quand docker run réunit création et démarrage. À l’arrêt, le processus principal reçoit SIGTERM, puis SIGKILL après dix secondes par défaut sous Linux, de quoi fermer proprement ses connexions. Trois options reviennent sans cesse :
-dlance le conteneur en arrière-plan ;--rmle supprime avec ses volumes anonymes dès sa sortie ;--namelui attribue un nom réutilisable.
La commande docker exec -it web sh ouvre un shell dans un conteneur actif, et docker container prune efface les conteneurs arrêtés.
Écrire un Dockerfile lisible
Un Dockerfile est un fichier texte sans extension qui décrit la construction d’une image, instruction par instruction :
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
USER node
EXPOSE 3000
CMD ["node", "src/index.js"]
FROM choisit l’image de base, WORKDIR le répertoire de travail, COPY apporte des fichiers de l’hôte et RUN exécute une commande pendant la construction. USER change d’utilisateur, EXPOSE signale le port écouté, CMD fixe la commande de démarrage.
L’ordre compte. Docker réutilise le cache d’une étape tant que sa commande et ses fichiers restent inchangés, mais une couche invalidée entraîne toutes les suivantes. Copier les dépendances avant le code évite de tout réinstaller à chaque retouche. La construction se lance par docker build -t mon-api:1.0 ., le point final désignant le contexte transmis au build. Un fichier .dockerignore en écarte node_modules et les identifiants locaux.

Volumes et montages : garder les données hors du conteneur
Ce qu’un conteneur écrit dans sa couche inscriptible disparaît avec lui. Les données d’une base doivent donc vivre ailleurs. Docker propose trois montages, et le volume nommé reste le choix par défaut :
- le volume, géré par Docker, survit à la suppression des conteneurs et se partage entre eux ;
- le montage lié (bind mount) branche un dossier précis de l’hôte, utile pour du code source ou un fichier de configuration ;
- le montage tmpfs réside en mémoire et s’efface à l’arrêt du conteneur.
docker volume create site
docker run -d -p 8080:80 -v site:/usr/share/nginx/html nginx:alpine
docker volume inspect site
Détail qui surprend : un volume vide monté sur un dossier déjà rempli dans l’image en reçoit une copie. Le montage lié laisse, lui, un processus du conteneur modifier ou effacer des fichiers de l’hôte : l’option :ro le passe en lecture seule. Avec -v, un dossier source absent est créé en silence, alors que --mount renvoie une erreur et débusque la faute de frappe.
Réseau et ports : exposer un service sans l’ouvrir à tous
L’option -p 8080:80 relie le port 8080 de l’hôte au port 80 du conteneur. Sans adresse précisée, Docker publie sur toutes les interfaces, une publication que la documentation juge non sécurisée par défaut. Deux réflexes :
- écrire
-p 127.0.0.1:8080:80pour réserver le service à l’hôte ; - retenir que les ports publiés contournent les règles d’ufw ou de firewalld, d’après la page d’installation pour Ubuntu.
Ce second point piège quiconque a soigné son pare-feu en suivant un guide pour durcir l’accès SSH d’un serveur.
Entre conteneurs, un réseau dédié vaut mieux que le bridge par défaut, où les conteneurs ne se joignent que par adresse IP et où atterrissent tous ceux lancés sans --network. Un réseau créé par l’utilisateur résout les noms : sur app-net, l’API répond sous le nom api.
docker network create app-net
docker run -d --name api --network app-net mon-api:1.0

Assembler plusieurs services avec Docker Compose
Quand une API et une base cohabitent, mieux vaut décrire l’ensemble pour Docker Compose dans un fichier compose.yaml :
services:
api:
build: .
ports: ["127.0.0.1:3000:3000"]
environment:
DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/app
db:
image: postgres:17
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes: ["pgdata:/var/lib/postgresql/data"]
volumes:
pgdata:
Compose crée un réseau <projet>_default et inscrit chaque service dans un DNS interne : l’API joint la base sous le nom db, sur le port du conteneur, jamais sur un port publié. La variable DB_PASSWORD, lue dans l’environnement du shell, garde le mot de passe hors du fichier versionné.
docker compose up -d démarre l’ensemble et docker compose logs -f api suit les journaux. docker compose down retire conteneurs et réseau mais conserve les volumes nommés, sauf avec l’option -v. Pour une API bâtie selon les principes d’une API REST soignée, ce fichier devient l’environnement partagé de l’équipe.
Trois réflexes pour des images saines dès le départ
Les bonnes pratiques de Docker retiennent trois habitudes de départ :
- partir d’une image légère : Alpine pèse moins de 6 Mo tout en restant une distribution Linux complète, et la construction en plusieurs étapes (multi-stage) ne garde que le résultat utile ;
- basculer vers un utilisateur non root avec
USERdès que le service tourne sans privilèges, comme le comptenodedes images Node officielles ; - garder les secrets hors de l’image :
ARGetENVrestent inscrits dans l’image finale, alors qu’un montage de secret n’existe que le temps d’une instructionRUN.
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci
docker build --secret id=npmrc,src=$HOME/.npmrc -t mon-api:1.0 .
Prochaine étape pour débuter avec Docker : conteneuriser un petit projet existant avec un Dockerfile court, un volume nommé et un fichier Compose, puis tout recréer pour vérifier que les données ont survécu.
Questions courantes sur Docker
Quelle différence entre Docker et Docker Hub ?
Docker désigne l’outil : le client en ligne de commande et le démon qui construisent, lancent et distribuent les conteneurs. Docker Hub est un service en ligne, le registre public que Docker interroge par défaut quand une image manque sur la machine. La comparaison avec Git et GitHub tient assez bien : l’un travaille en local, l’autre héberge et partage le résultat. Rien n’oblige à publier ses images sur Docker Hub, un registre privé remplit le même rôle.
Docker Desktop est-il indispensable pour débuter ?
Sur Linux, non : Docker Engine s’installe sur les principales distributions et couvre tout l’apprentissage en ligne de commande. Sous Windows et macOS, Docker Desktop reste la voie indiquée par la documentation pour obtenir le moteur, Docker Compose compris. Son interface graphique aide à inspecter conteneurs, images et volumes, mais chaque notion vue plus haut se pratique au terminal. Les conditions de licence en entreprise méritent une lecture attentive avant tout déploiement.
Un conteneur est-il aussi isolé qu’une machine virtuelle ?
Pas tout à fait. Une machine virtuelle possède son propre noyau, alors que les conteneurs d’un même hôte partagent celui de la machine et reposent sur l’isolation du noyau Linux. Cette légèreté fait leur force, mais la frontière entre deux conteneurs reste plus mince qu’entre deux machines virtuelles. D’où les réflexes décrits plus haut : utilisateur non root, ports liés à l’adresse locale, secrets hors des images.