Docker est la plateforme de référence de conteneurisation : elle vous permet d'empaqueter une application et ses dépendances dans une image, un artefact immuable, puis de l'exécuter partout à l'identique sous forme de conteneur, un processus isolé et léger qui démarre en quelques secondes. Cela règle le fameux « ça marche sur ma machine » : le conteneur embarque tout ce qu'il faut pour tourner, du code aux bibliothèques système.
Cette page ouvre la formation Docker : elle vous explique comment elle est organisée, module par module, puis vous donne une référence rapide pour revenir sur une commande ou un choix.
Que faut-il savoir avant de commencer ?
Section intitulée « Que faut-il savoir avant de commencer ? »La formation Docker suppose que vous savez déjà ce qu'est un conteneur et que vous êtes à l'aise dans un terminal Linux. Le premier acquis vient de la formation Introduction à la conteneurisation, le second de la formation Linux.
La formation Introduction à la conteneurisation vous fait comprendre qu'un conteneur est un processus ordinaire de la machine, à qui le noyau donne une vue restreinte du système. Les namespaces isolent ce qu'il voit, et les cgroups plafonnent ce qu'il consomme : vous les créez à la main dans Un conteneur à la main avec unshare et nsenter puis Limiter un conteneur : cgroups v2 et capabilities. Vous y apprenez aussi la différence avec une machine virtuelle : celle-ci émule un ordinateur complet avec son propre noyau, alors qu'un conteneur partage le noyau de l'hôte, ce qui explique son démarrage en quelques secondes.
Une image OCI est une archive standardisée qui fournit le système de fichiers et la configuration de départ d'un conteneur. Elle s'étudie avec Comprendre OCI : image, distribution et runtime et Lire une image OCI et vérifier son digest.
Un runtime comme runc exécute ensuite cette image en reproduisant les gestes du noyau vus plus tôt, dans Exécuter un bundle OCI avec runc. La leçon Runtime, moteur, orchestrateur : qui fait quoi situe ensuite Docker par rapport à lui.
Côté Linux, la formation Docker n'utilise qu'un socle réduit, que la page d'accueil de la formation Linux détaille : naviguer et éditer des fichiers dans un terminal, lire et modifier les droits d'un fichier et d'un utilisateur, afficher et arrêter des processus, et comprendre le réseau de base (adresse IP, port, résolution de nom). Ces notions reviennent dans les modules sur les volumes, l'arrêt propre d'un conteneur et la publication de ports.
Si ces acquis vous manquent, suivez d'abord la formation Introduction à la conteneurisation, puis reprenez les modules de Linux qui correspondent à ce qui vous bloque, avant de revenir ici.
Comment la formation Docker est-elle organisée ?
Section intitulée « Comment la formation Docker est-elle organisée ? »La formation compte quatorze modules d'enseignement, répartis en trois niveaux : « Utiliser Docker » (lancer, construire, publier, observer, relier et persister), « Composer et exploiter une application » (Compose), puis « Fabriquer, durcir et industrialiser » (images avancées, moteur, durcissement, chaîne d'images). Les modules suivent un ordre de lecture conseillé, et votre avancement leçon par leçon se suit sur la page Mon parcours.
Toutes les commandes de la formation sont mesurées sur Docker Engine 29.9.2, Compose 5.6.1 et Buildx 0.38.1, installés sur Debian 13.
Les durées citées plus bas sont celles du programme : chaque leçon porte la sienne, et un module annonce la somme de ses leçons publiées. Toutes les leçons et épreuves du programme ont une page publiée. Cette page ne lie que les leçons publiées.
Découvrir Docker et lancer un conteneur
Section intitulée « Découvrir Docker et lancer un conteneur »Ce premier module (environ 2 h 45) pose ce qu'est un conteneur avant d'en lancer un. La leçon Conteneurs ou machines virtuelles : que choisir ? compare les deux modèles, puis Images, conteneurs et registres : l'anatomie retrace le chemin d'une commande docker jusqu'au processus. Vous installez ensuite Docker Engine 29 et prouvez qu'il fonctionne, puis vous apprenez à lancer un conteneur et à choisir ce qu'il exécute. L'épreuve « mettre un service en marche » clôt le module.
Construire et publier une image
Section intitulée « Construire et publier une image »Un conteneur part d'une image, et ce module (environ 3 h 25) vous apprend à la fabriquer puis à la publier. Il commence par Écrire un Dockerfile, puis choisir et maintenir une image de base. Il enchaîne avec Docker USER, qui explique comment exécuter une image en non-root sans la casser, et avec l'organisation des couches et le cache de construction. La leçon Publier et récupérer une image vous fait nommer l'image, vous connecter avec un jeton à droits limités, puis la pousser et la récupérer par tag ou par digest. L'épreuve « livrer une première image » vérifie le tout.
Observer et dépanner un conteneur
Section intitulée « Observer et dépanner un conteneur »Ce module (environ 2 h 20) sert à comprendre pourquoi un conteneur s'arrête, redémarre ou refuse de démarrer. Le cycle de vie, le PID 1 et l'arrêt propre expliquent les états et les codes 137 et 143. Inspecter un conteneur en marche donne quatre commandes pour quatre questions, et Lire un échec de démarrage apprend à interpréter les codes 125, 126 et 127 et les boucles de redémarrage. L'épreuve « remettre trois conteneurs en service » vous met en situation.
Exposer et relier des conteneurs
Section intitulée « Exposer et relier des conteneurs »Ce module (environ 2 h 10) traite de ce qui est ouvert, et à qui. Publier un port sans exposer tout l'hôte distingue les trois formes de -p. Ensuite, le réseau par défaut ou un réseau à soi montre que seul un réseau créé par vous résout les noms de conteneurs, et isoler un conteneur du réseau compare none et le réseau interne. L'épreuve « exposer une application sans exposer sa base » en fait la preuve.
Conserver ses données
Section intitulée « Conserver ses données »Un conteneur recréé perd ses fichiers : ce module (environ 1 h 35) vous apprend à les garder. La leçon Volumes Docker compare volume nommé, bind mount et tmpfs. Celle sur les droits d'un volume départage les trois causes d'un accès refusé. Vous terminez par l'épreuve « remettre un conteneur en service ».
Décrire une application avec Compose
Section intitulée « Décrire une application avec Compose »Ce module (environ 3 h 15) ouvre le deuxième niveau : vous passez de plusieurs docker run à un fichier unique. La leçon Décrire une application avec Compose pose deux services, un réseau et un volume. Elle est suivie de l'interpolation et des fichiers d'environnement, de l'organisation des réseaux d'une stack et de la persistance des données d'une stack recréée. L'épreuve « remettre une stack en service » conclut.
Fiabiliser une stack
Section intitulée « Fiabiliser une stack »Une stack qui démarre n'est pas encore une stack fiable, et ce module (environ 3 h 45) s'en occupe. Vous y injectez des secrets en connaissant leurs limites, vous réglez le démarrage, la disponibilité et la santé, vous encadrez ressources et redémarrage, puis vous écrivez des variantes explicites pour le développement et le déploiement. L'épreuve « fiabiliser une stack » vérifie ces réglages.
Exploiter et restaurer une stack
Section intitulée « Exploiter et restaurer une stack »Ce module (environ 2 h 45) termine le deuxième niveau. Il apprend à lire les journaux et à attribuer une saturation, à sauvegarder et restaurer une application, puis à mettre à jour une stack et revenir en arrière sans perdre les données. L'épreuve « exploiter et restaurer une stack » clôt le module et le niveau.
Fabriquer des images avancées
Section intitulée « Fabriquer des images avancées »Le troisième niveau s'ouvre sur ce module (environ 6 h 15), qui reprend la fabrication d'images là où le premier niveau s'est arrêté. Vous commencez par lire une image OCI et son identité : tag, index, manifeste, digest et plateforme. Vous apprenez ensuite à changer de socle sans casser l'application, puis à séparer construction et exécution avec un build multi-étapes. La leçon BuildKit : secrets de build et accès privé traite des secrets de build, et celle sur le multi-architecture de buildx et de l'émulation. L'épreuve « reconstruire une image pour deux architectures » vérifie le résultat.
Tester, réduire et livrer une image
Section intitulée « Tester, réduire et livrer une image »Ce module apprend à décider qu'une image est prête, puis à la livrer. Ses cinq leçons et son épreuve représentent environ 5 h 35. Vous testez le contrat d'une image avec un script qui la refuse si elle est inutilisable, puis vous optimisez sa taille. Vous servez ensuite un registre de confiance et vous vous y authentifiez, vous épinglez un socle et vous livrez hors ligne par docker save, puis vous exportez une image sans démon avec Skopeo. L'épreuve « livrer une image utilisable ailleurs » vérifie qu'un client vierge exécute votre livraison.
Comprendre ce que fait le moteur
Section intitulée « Comprendre ce que fait le moteur »Ce module explique ce qui se passe réellement quand un conteneur démarre. Ses quatre leçons et son épreuve représentent environ 2 h 50. Vous commencez par mesurer l'isolation d'un conteneur avec les namespaces et les cgroups, puis vous suivez la chaîne d'exécution du client docker jusqu'à runc. La leçon Brider un conteneur règle ensuite le processeur, les ulimits et la mémoire partagée, et Plafonner la mémoire et le nombre de tâches apprend à poser ces deux plafonds, à lire leur effet dans le cgroup et à reconnaître un OOM ou une saturation de tâches. L'épreuve « contenir un conteneur gourmand » clôt le module.
Administrer le démon
Section intitulée « Administrer le démon »Le démon Docker est l'élément que toutes vos applications partagent, et ce module vous apprend à le tenir. Ses six leçons publiées et son épreuve représentent environ 5 h. La leçon Administrer le démon et ses contextes (environ 35 min) montre où le démon lit sa configuration, modifie daemon.json par fusion avec jq puis dockerd --validate sans casser le démon, distingue reload et restart, ferme une écoute TCP posée par une surcharge systemd, puis administre un hôte distant par un contexte SSH et prouve qu'une clé non autorisée est refusée. La leçon Interposer un proxy devant l'API Docker (environ 40 min) montre pourquoi monter docker.sock en :ro ne protège pas.
La leçon Faire tourner les journaux, et reprendre du disque (environ 30 min) borne les journaux d'un conteneur, prouve que la rotation a lieu, mesure l'espace par catégorie et libère un système de fichiers plein sans recréer le conteneur. La leçon Mettre à jour le moteur et sauvegarder sa configuration (environ 35 min) monte Docker Engine d'une version à l'autre sur un hôte dont les paquets sont retenus, avec live-restore et une donnée témoin, puis revient en arrière. La leçon Retirer les accès directs au moteur (environ 45 min) inventorie qui peut parler au socket Docker, par le groupe docker, une ACL ou un montage dans un conteneur, puis retire chaque accès et vérifie qu'il est vraiment fermé. La leçon Exécuter Docker en rootless (environ 55 min) installe un moteur sous un compte sans privilège à côté du moteur système, lit la correspondance des UID, mesure ce qui change pour le réseau, les ressources et AppArmor, puis garde le démon actif sans session ouverte. L'épreuve « reprendre un hôte Docker » (environ 60 min) clôt le module : un hôte laissé sans suivi, à reprendre sans perdre ses volumes nommés.
Durcir l'exécution
Section intitulée « Durcir l'exécution »Ce module vise à réduire ce qu'un conteneur compromis peut faire. Ses six leçons publiées et son épreuve représentent environ 5 h 20. La leçon Durcir le runtime : capabilities et privilèges (environ 30 min) retire toutes les capabilities avec --cap-drop ALL, retrouve et justifie la seule exception dont le service a besoin, bloque les gains de privilèges avec no-new-privileges, n'ouvre qu'un périphérique avec --device au lieu de --privileged, et liste les réglages à ne jamais poser. La leçon Garder un secret hors de l'environnement (environ 25 min) montre pourquoi -e se lit dans docker inspect et dans /proc/1/environ, puis fournit le secret par un fichier monté en lecture seule, la convention _FILE et un secret Compose de type file. Les secrets de build se traitent dans BuildKit : secrets de build et accès privé. La leçon Racine en lecture seule, et arrêt sans perte (environ 50 min) fige la racine d'un conteneur PostgreSQL avec --read-only, borne ses tmpfs, prépare son volume, puis compare docker stop et docker kill sur une transaction en cours. La leçon Retrouver des données orphelines sans tout effacer (environ 60 min) retrouve un volume qui n'est plus attaché, le lit sans risque et le sauvegarde, le rattache à Compose après un changement de nom de projet, puis ne supprime que ce qui est jetable. La leçon Confiner par profils : seccomp et AppArmor (environ 60 min) lit les profils actifs d'un conteneur, attribue un refus à sa couche, dérive un profil seccomp du profil par défaut et écrit un profil AppArmor qui laisse encore le service s'arrêter proprement et survit au redémarrage. La leçon Diagnostiquer réseau et pare-feu (environ 35 min) suit un paquet jusqu'au conteneur, localise le saut et la règle qui le refusent, corrige une seule règle et le prouve par des sondes positives et négatives, sans jamais désactiver le pare-feu. L'épreuve « durcir sans casser » (environ 60 min) clôt le module.
Industrialiser la chaîne des images
Section intitulée « Industrialiser la chaîne des images »Le dernier module met la fabrication d'images en production. La leçon Automatiser build, tests et publication (environ 40 min) écrit un script de CI qui construit l'image d'un commit, la teste avec Compose, puis publie une archive avec sa provenance. La leçon Partager le cache de build en CI, et promouvoir une image entre registres (environ 35 min) exporte le cache par un registre, choisit entre les modes min et max sur des mesures, puis copie une image d'un registre à l'autre sans la reconstruire. Elle ne couvre pas la promotion entre environnements : la leçon Promouvoir le même artefact entre deux environnements (environ 55 min) la traite, en transférant une archive vers un second hôte et en déployant avec --no-build --pull never pour qu'aucun environnement ne reconstruise l'image.
La leçon Vérifier ce que contient une image, et qui l'a signée (environ 50 min) scanne une image avec Trivy, écrit une barrière qui refuse une CVE nommée, puis signe une archive avec une autorité locale et vérifie la chaîne, l'identité et la signature ; Cosign et DOCKER_CONTENT_TRUST n'y sont que situés.
La leçon Préparer l'exploitation, et reconnaître les limites d'un mono-hôte (environ 40 min) mesure un SLO, relie les alertes aux signaux que Docker expose, chronomètre une restauration, puis vérifie la reprise du service après le redémarrage de l'hôte, et ce qu'un seul hôte ne peut pas garantir. L'épreuve finale « reprendre un service inconnu » (environ 3 h) clôt la formation : une application à livrer, durcir, faire tomber et rétablir de bout en bout, notée sur l'état final. Le module représente environ 6 h 40.
Référence rapide
Section intitulée « Référence rapide »Vous voulez une page "réponse immédiate" ? Cette section est faite pour ça.
Concepts (image/conteneur/layers), ce qu'il faut retenir
- Image : artefact immuable (comme un binaire buildé ou un paquet).
- Conteneur : process isolé (comme un service systemd) + FS éphémère.
- Layer : diff (comme un commit Git) empilé et cacheable.
- Volume : stockage persistant (comme un PVC local, mais côté Docker).
- Réseau bridge : réseau NAT isolé (comme une VRF "par défaut" Docker).
CLI, les commandes qui comptent vraiment
- "Je lance" :
docker run … - "Je vois" :
docker ps,docker images - "Je comprends" :
docker logs,docker inspect - "J'entre" :
docker exec -it … sh - "Je nettoie" :
docker rm,docker rmi,docker system prune
Volumes, choix rapide
- Bind mount : dev / code local / debug rapide.
- Volume nommé : prod / données applicatives / DB.
- tmpfs : secret temporaire / perf / rien sur disque.
Réseaux, choix rapide
- bridge : cas standard (app multi-conteneurs sur 1 hôte).
- host : perf max, isolation réseau minimale.
- overlay : multi-hôtes (Swarm) / réseau distribué.
Dépannage, "je fais quoi quand ça marche pas"
- Si ça crash : exit code + logs +
inspect(ordre fixe). - Si ça ne répond pas : ports publish + IP/route + DNS + healthcheck.
- Si ça ne pull pas : auth registry + DNS + proxy + certs.
Sécurité, règles simples
- Évitez
root(rootless si possible). - Retirez les capabilities inutiles, read-only FS si possible.
- Scannez les images, mettez à jour régulièrement.
- Secrets hors image + hors variables exposées.
→ Durcir le runtime : capabilities et privilèges → Garder un secret hors de l'environnement
Repères : standards et écosystème
Section intitulée « Repères : standards et écosystème »La frise se lit de haut en bas, de 2010 à 2024 : elle place les dates qui expliquent pourquoi l'écosystème ne dépend plus d'un seul outil, avec en relief la dépréciation de dockershim par Kubernetes en 2020 (Kubernetes 1.20), suivie de son retrait en 2022 (Kubernetes 1.24).
FAQ, Questions fréquentes
Section intitulée « FAQ, Questions fréquentes »Définition
- Conteneur : unité légère et portable qui embarque l'application et toutes ses dépendances
- Image : modèle immuable servant de base aux conteneurs
- Registre : dépôt centralisé d'images (Docker Hub, registres privés)
Avantages clés
- Portabilité : "fonctionne partout" (dev, test, prod)
- Isolation : chaque conteneur a son propre système de fichiers
- Légèreté : partage le noyau de l'hôte (vs machines virtuelles)
- Reproductibilité : même environnement sur tous les systèmes
Architecture
┌─────────────────────────────────┐
│ Applications Docker │
├─────────────────────────────────┤
│ Conteneurs (isolés) │
├─────────────────────────────────┤
│ Docker Engine (démon) │
├─────────────────────────────────┤
│ Système d'exploitation │
└─────────────────────────────────┘
Cas d'usage
- Développement : environnements identiques pour toute l'équipe
- CI/CD : tests automatisés dans des conteneurs jetables
- Microservices : déploiement et mise à l'échelle indépendants
Rôles principaux
| Fonction | Description |
|---|---|
| Build | Créer des images à partir de Dockerfile |
| Run | Démarrer et arrêter les conteneurs |
| Isolation | Namespace, cgroups, capabilities |
| Réseau | Créer des réseaux virtuels entre conteneurs |
| Stockage | Gérer les volumes et bind mounts |
| Sécurité | Appliquer les politiques de sécurité |
Composants Docker Engine
# Vérifier le moteur
docker version
docker info
# Architecture
systemctl status docker # Démon dockerd
docker ps # CLI client
Alternatives à Docker
- Podman : compatible Docker, sans démon (plus sécurisé)
- containerd : runtime bas niveau (utilisé par Kubernetes)
- CRI-O : optimisé pour Kubernetes
| Moteur | Type | Particularités | Cas d'usage |
|---|---|---|---|
| Docker | Container engine complet | Écosystème mature, Docker Hub, Compose | Développement, production générale |
| Podman | Compatible Docker, daemonless | Sans démon root, pods, compatible CLI Docker | Sécurité, environnements non-root |
| containerd | Runtime bas niveau | Léger, intégré dans Kubernetes et Docker | Production Kubernetes |
| CRI-O | Runtime Kubernetes | Optimisé pour CRI, images OCI uniquement | Clusters Kubernetes dédiés |
| LXC/Incus | Conteneurs système | Machines virtuelles légères, init complet | Migration VM → conteneurs |
Exemples de commandes
# Docker (avec démon)
sudo docker run -d nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
# Podman (sans démon)
podman run -d docker.io/library/nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
podman pod create mon-pod # Support natif des pods
# containerd (via ctr)
sudo ctr images pull docker.io/library/nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
sudo ctr run docker.io/library/nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da nginx-ctr
Comment choisir ?
- Docker : développement, apprentissage, écosystème riche
- Podman : sécurité, CI/CD sans privilèges root
- containerd/CRI-O : clusters Kubernetes en production
Configuration système
| Aspect | Configuration | Justification |
|---|---|---|
| Stockage | Partition dédiée /var/lib/docker |
Éviter saturation du système si images/volumes consomment l'espace |
| Logs | Driver json-file avec rotation |
max-size: 10m, max-file: 3 pour limiter la croissance |
| Démon | Fichier /etc/docker/daemon.json |
Centraliser la config (log-driver, log-opts, live-restore, etc.) |
Sécurité réseau
"icc": false désactive la communication entre conteneurs du réseau par défaut.{
"icc": false,
"userland-proxy": false,
"no-new-privileges": true
}
Limitations de ressources
# Limiter CPU et mémoire
docker run -d \
--memory="512m" \
--memory-swap="1g" \
--cpus="1.5" \
--restart=unless-stopped \
mon-app:1.0.0
Sécurité des conteneurs
# Dans le Dockerfile
USER node # Ne pas exécuter en root
# Images de confiance
FROM node:24.22.2-alpine@sha256:8a32c8cf649a49915a66e81e7a609223c708d0adabf288ee3f4077d765542f85 # Image officielle minimale, épinglée par digest
# Health checks
HEALTHCHECK --interval=30s --timeout=3s \
CMD node healthcheck.js
Monitoring et observabilité
# Métriques Docker
docker stats
# Logs centralisés
# Configurer un driver de logs (syslog, fluentd, splunk)
Gestion des secrets
# Utiliser Docker secrets (Swarm) ou variables d'environnement sécurisées
docker secret create db_password ./password.txt
Checklist production
- Partition dédiée pour
/var/lib/docker - Rotation des logs configurée
- Utilisateurs non-root dans les conteneurs
- Ressources limitées (CPU/RAM)
- Images officielles et régulièrement mises à jour
- Health checks sur tous les services
- Monitoring actif (Prometheus, Grafana)
- Backups automatisés des volumes
Principe du moindre privilège
# Limiter les capabilities Linux
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE mon-app:1.0.0
# Exécuter en utilisateur non-root
docker run --user 1000:1000 mon-app:1.0.0
# Conteneur en lecture seule
docker run --read-only --tmpfs /tmp mon-app:1.0.0
# Désactiver les nouveaux privilèges
docker run --security-opt=no-new-privileges mon-app:1.0.0
Modules de sécurité (LSM)
# AppArmor (Ubuntu/Debian)
docker run --security-opt apparmor=docker-default nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
# SELinux (RHEL/CentOS)
docker run --security-opt label=type:svirt_apache_t nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
Confiance des images
Docker Content Trust n'existe plus. La commandedocker trust a été retiréede Docker Engine 29, et la variable
DOCKER_CONTENT_TRUST y est devenueinerte : un
docker pull la trouve, l'ignore et réussit sans le moindreavertissement. La poser aujourd'hui donne une fausse impression de vérification.
# Vérifier une signature : Cosign, hors du moteur Docker
cosign verify --certificate-identity-regexp '.*' \
--certificate-oidc-issuer-regexp '.*' nginx:stable-alpine
# Figer l'image par son empreinte, ce qui ne dépend d'aucun outil
docker pull nginx@sha256:...
# Scanner les vulnérabilités
docker run --rm ghcr.io/aquasecurity/trivy:0.76.1@sha256:790fd66d1697395d8693d1acaa1ea702406a20f109b6fc7bac8db623eca6c06c image nginx:1.31.8-alpine@sha256:785835ea65db4bba6f021acc0f3be91b0fef76a53fe41f8588c6698d2aed0606
Sécurité réseau
# Filtrage réseau (réseau personnalisé)
docker network create --internal backend
# Pas d'exposition inutile de ports
# ❌ docker run -p 0.0.0.0:3306:3306 mysql:8.4.13@sha256:a81d043930e51745522bd5c430961cf8286f0a23f0a9a2a6e0108f7ea71b0902
# ✅ docker run -p 127.0.0.1:3306:3306 mysql:8.4.13@sha256:a81d043930e51745522bd5c430961cf8286f0a23f0a9a2a6e0108f7ea71b0902
Gestion des secrets
# Docker Swarm secrets
echo "mon_mot_de_passe" | docker secret create db_password -
docker service create --secret db_password mon-api
# Variables d'environnement (fichier séparé)
docker run --env-file .env.production mon-app:1.0.0
Audit et monitoring
# Audit des événements Docker
auditctl -w /var/lib/docker -k docker
auditctl -w /usr/bin/docker -k docker
# Logs centralisés
# Configurer syslog/fluentd dans /etc/docker/daemon.json
Images minimales
# Préférer Alpine ou scratch
FROM alpine:3.24.3@sha256:be2656061b536c1883c4034790e21d0a09c5aaaf51968b89368a3c0371ea2c9a # image minimale, épinglée par digest
# Multi-stage pour exécutables statiques
FROM scratch
COPY --from=builder /app/binary /
ENTRYPOINT ["/binary"]
Checklist sécurité
- Utilisateur non-root dans tous les conteneurs
- Capabilities minimales (--cap-drop=ALL)
- AppArmor/SELinux activés
- Signatures vérifiées avec Cosign ou Notation, et images figées par digest
- Scan régulier des images (Trivy, Clair)
- Réseau interne pour services backend
- Secrets gérés via Docker secrets ou vault
- Audit actif sur /var/lib/docker
- Images minimales (Alpine/scratch)
- Mises à jour régulières des images de base
Comparaison des types
| Type | Emplacement | Gestion | Cas d'usage |
|---|---|---|---|
| Volumes | /var/lib/docker/volumes/ |
Docker (recommandé) | Bases de données, données applicatives |
| Bind mounts | Chemin absolu sur l'hôte | Utilisateur | Développement, fichiers de configuration |
| tmpfs | Mémoire RAM uniquement | Éphémère | Secrets, données temporaires sensibles |
Commandes volumes
# Créer un volume
docker volume create mon-volume
# Lister les volumes
docker volume ls
# Inspecter un volume
docker volume inspect mon-volume
# Utiliser un volume
docker run -v mon-volume:/data postgres:18.6@sha256:3a4264520e121176619f54ff867d12774bc81e95e7b84db58d63bccdb6144b81
# Supprimer un volume
docker volume rm mon-volume
Exemples Docker Compose
services:
db:
image: postgres:18.6@sha256:3a4264520e121176619f54ff867d12774bc81e95e7b84db58d63bccdb6144b81
volumes:
- db-data:/var/lib/postgresql/data # Volume nommé
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro # Bind mount
volumes:
db-data: # Déclaration du volume
Backup et restore
# Sauvegarder un volume
docker run --rm -v mon-volume:/data -v $(pwd):/backup alpine:3.24.3@sha256:be2656061b536c1883c4034790e21d0a09c5aaaf51968b89368a3c0371ea2c9a tar czf /backup/data.tar.gz /data
# Restaurer un volume
docker run --rm -v mon-volume:/data -v $(pwd):/backup alpine:3.24.3@sha256:be2656061b536c1883c4034790e21d0a09c5aaaf51968b89368a3c0371ea2c9a tar xzf /backup/data.tar.gz -C /
Plugins de stockage
- Local : stockage par défaut sur l'hôte
- NFS : partage réseau entre plusieurs hôtes
- SSHFS : montage distant via SSH
- Cloud : Azure Files, AWS EFS, Google Filestore
Comparaison
| Aspect | Image | Conteneur |
|---|---|---|
| Nature | Modèle statique, immuable | Instance dynamique, éphémère |
| Stockage | Système de fichiers en couches (layers) | Couche en lecture/écriture au-dessus de l'image |
| État | Aucun état (stateless) | Possède un état (stateful) |
| Partage | Peut servir de base à plusieurs conteneurs | Isolé, ne peut pas être partagé |
| Cycle de vie | Créée une fois, utilisée plusieurs fois | Créé, démarré, arrêté, supprimé |
Commandes
# Lister les images
docker images
# Lister les conteneurs en cours d'exécution
docker ps
# Lister tous les conteneurs (actifs et arrêtés)
docker ps -a
# Créer un conteneur à partir d'une image
docker run nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da # Image nginx → Conteneur nginx
Structure en couches
Chaque image est composée de layers (couches) en lecture seule. Le conteneur ajoute une couche en lecture/écriture au-dessus.Modes réseau
| Mode | Description | Cas d'usage |
|---|---|---|
| bridge | Réseau virtuel isolé (par défaut) | Communication entre conteneurs sur un même hôte |
| host | Partage la pile réseau de l'hôte | Performance maximale (pas de NAT) |
| overlay | Réseau multi-hôtes (Swarm/Kubernetes) | Clusters de conteneurs sur plusieurs machines |
| macvlan | Attribution d'adresses MAC virtuelles | Intégration au réseau physique existant |
| none | Aucun réseau | Isolation réseau complète |
Exemple : Réseau bridge personnalisé
# Créer un réseau bridge
docker network create mon-reseau
# Lancer des conteneurs dans ce réseau
docker run -d --name db --network mon-reseau postgres:18.6@sha256:3a4264520e121176619f54ff867d12774bc81e95e7b84db58d63bccdb6144b81
docker run -d --name api --network mon-reseau -p 3000:3000 mon-api:1.0.0
# Les conteneurs peuvent communiquer par leur nom
# Depuis 'api' : psql -h db -U postgres
Exposition de ports
# Mapper un port hôte → conteneur
docker run -p 8080:80 nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da # localhost:8080 → nginx:80
# Publier tous les ports EXPOSE du Dockerfile
docker run -P nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
DNS interne
Docker fournit un DNS intégré : les conteneurs se résolvent mutuellement par leur nom sur les réseaux personnalisés (bridge/overlay).Avantages
- Simplicité : un fichier
compose.yamlremplace plusieursdocker run - Reproductibilité : toute l'équipe utilise la même stack
- Gestion du cycle de vie : démarrage/arrêt/rebuild de tous les services en une commande
- Environnements multiples : profils dev/test/prod dans le même fichier
Exemple complet
services:
db:
image: postgres:18.6-alpine3.24@sha256:10a5c69a83035ab5239f5620d708520e8b28f5aa1f2b20143e6024532edadfb5
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
secrets:
- db_password
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
interval: 10s
api:
build: ./api
env_file: .env
depends_on:
db:
condition: service_healthy
networks:
- backend
- frontend
web:
image: nginx:1.31.8-alpine@sha256:785835ea65db4bba6f021acc0f3be91b0fef76a53fe41f8588c6698d2aed0606
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- frontend
profiles:
- prod
networks:
backend:
frontend:
volumes:
db-data:
secrets:
db_password:
file: ./db_password.txt
Commandes essentielles
# Démarrer tous les services
docker compose up -d
# Voir les logs en temps réel
docker compose logs -f api
# Lister les conteneurs
docker compose ps
# Exécuter une commande dans un service
docker compose exec api sh
# Arrêter et supprimer
docker compose down
# Activer un profil spécifique
docker compose --profile prod up -d
Variables d'environnement
# Fichier .env
API_PORT=3000
DB_VERSION=15
# Référencées dans compose.yaml
ports:
- "${API_PORT}:3000"
Comparaison
| Aspect | Docker | Kubernetes |
|---|---|---|
| Niveau | Conteneur individuel | Cluster de conteneurs |
| Scope | Machine unique | Multi-machines (cluster) |
| Objectif | Empaqueter et exécuter | Orchestrer et automatiser |
| Scaling | Manuel (docker run x N) |
Automatique (HorizontalPodAutoscaler) |
| Haute disponibilité | Non (conteneur unique) | Oui (réplication, self-healing) |
| Configuration | CLI/compose.yaml | Manifestes YAML (Deployment, Service, etc.) |
| Complexité | Simple, facile à apprendre | Courbe d'apprentissage élevée |
Exemples
Docker : exécution simple# Lancer 3 répliques manuellement
docker run -d --name web1 -p 8001:80 nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
docker run -d --name web2 -p 8002:80 nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
docker run -d --name web3 -p 8003:80 nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
# Pas de load balancing automatique
# Pas de redémarrage automatique si crash
Kubernetes : orchestration automatiqueapiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3 # 3 répliques automatiques
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 80
targetPort: 80
# Kubernetes gère automatiquement :
kubectl apply -f deployment.yaml
# → 3 pods répartis sur le cluster
# → Load balancing automatique
# → Redémarrage auto si crash (self-healing)
# → Rolling updates sans downtime
Fonctionnalités Kubernetes
- Auto-scaling : ajustement automatique du nombre de pods selon la charge (CPU/RAM)
- Self-healing : redémarrage automatique des pods en échec
- Rolling updates : remplacement progressif des Pods, sans interruption ; un canary ou un test A/B demande en plus plusieurs Deployments ou un outil dédié
- Service discovery : DNS interne pour communication entre services
- ConfigMaps & Secrets : gestion centralisée de la configuration
- Persistent Volumes : stockage persistant indépendant du cycle de vie des pods
Architecture
Docker :┌─────────────────┐
│ Machine │
│ ┌───┬───┬───┐ │
│ │C1 │C2 │C3 │ │ (Conteneurs isolés)
│ └───┴───┴───┘ │
│ Docker Engine │
└─────────────────┘
Kubernetes :┌────────────────────────────────────┐
│ Cluster K8s │
│ ┌─────────┐ ┌─────────┐ │
│ │ Node 1 │ │ Node 2 │ ... │
│ │ ┌─┬─┬─┐ │ │ ┌─┬─┐ │ │
│ │ │P│P│P│ │ │ │P│P│ │ │ (Pods répartis)
│ │ └─┴─┴─┘ │ │ └─┴─┘ │ │
│ └─────────┘ └─────────┘ │
│ Control Plane (API, Scheduler) │
└────────────────────────────────────┘
Quand utiliser quoi ?
| Contexte | Outil recommandé |
|---|---|
| Développement local | Docker + Docker Compose |
| Application simple (1-5 conteneurs) | Docker |
| Production à grande échelle (>10 conteneurs) | Kubernetes |
| Besoin de haute disponibilité | Kubernetes |
| Multi-cloud ou cloud hybride | Kubernetes |
| Équipe sans expertise DevOps | Docker (plus simple) |
Instructions principales
| Instruction | Rôle | Exemple |
|---|---|---|
| FROM | Image de base | FROM node:24.22.2-alpine@sha256:8a32c8cf649a49915a66e81e7a609223c708d0adabf288ee3f4077d765542f85 |
| WORKDIR | Répertoire de travail | WORKDIR /app |
| COPY | Copier des fichiers | COPY package*.json ./ |
| RUN | Exécuter des commandes | RUN npm install |
| EXPOSE | Documenter les ports | EXPOSE 3000 |
| ENV | Variables d'environnement | ENV NODE_ENV=production |
| CMD | Commande par défaut | CMD ["npm", "start"] |
| ENTRYPOINT | Point d'entrée fixe | ENTRYPOINT ["docker-entrypoint.sh"] |
Exemple multi-stage (optimisation)
# Étape 1 : Build
FROM node:24.22.2-alpine@sha256:8a32c8cf649a49915a66e81e7a609223c708d0adabf288ee3f4077d765542f85 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Étape 2 : Production
FROM node:24.22.2-alpine@sha256:8a32c8cf649a49915a66e81e7a609223c708d0adabf288ee3f4077d765542f85
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm ci --only=production
EXPOSE 3000
CMD ["node", "dist/index.js"]
Utilisation
# Construire une image
docker build -t mon-app:1.0 .
# Lancer un conteneur
docker run -p 3000:3000 mon-app:1.0
Bonnes pratiques
- Utiliser des images de base officielles et légères (Alpine)
- Créer un fichier .dockerignore (node_modules, .git)
- Minimiser les couches : regrouper les RUN
- Multi-stage builds : images finales plus petites
- Ne pas exécuter en root :
USER node
docker run, qui télécharge l'image si besoin puis démarre le conteneur. Pour un premier test :docker run hello-world:linux@sha256:5e22040d441e5fb3aed38368acbe8486b575d7018df38dbdfbc7311fbb2ef3a9
Pour lancer un serveur web Nginx en arrière-plan et le publier sur le port 8080 :docker run -d -p 8080:80 nginx:1.31.8@sha256:5ab5b0b01097420873a3f3330f44248e34a3c2a3e8d5ee30658aeae8cb7435da
L'option -d détache le conteneur (mode arrière-plan) et -p 8080:80 mappe le port. Vérifiez avec docker ps que le conteneur tourne. Le détail des options est dans le guide de la CLI Docker.Le cœur est libre, Docker Desktop a des conditions
Il faut distinguer les composants open source de l'application de bureau Docker Desktop.| Composant | Licence | Gratuit ? |
|---|---|---|
| Docker Engine (dockerd, CLI) | Apache 2.0 | Oui, sans condition |
| Docker Compose (plugin) | Apache 2.0 | Oui, sans condition |
| Docker Desktop | Propriétaire | Sous conditions |