MémentoAuteur : D. Dambreville · didierdambreville.github.io · licence CC BY 4.0

VM & Docker

Machines virtuelles · VirtualBox · KVM · WSL · conteneurs · images · réseaux · Compose · sécurité
docker ps chasse fixe, gras : à taper tel quel
conteneur italique : valeur à remplacer
Ctrl+C touche ou combinaison de touches
! piège fréquent ou commande destructrice

Deux façons d’isoler

Machines virtuelles
Appli AAppli B
Biblio­thèquesBiblio­thèques
Système invité + noyauSystème invité + noyau
Hyperviseur
Système hôte
Matériel
Conteneurs
Appli AAppli B
Biblio­thèquesBiblio­thèques
Moteur de conteneurs
Système hôte : noyau partagé
Matériel

La VM simule une machine entière ; le conteneur isole des processus qui partagent le noyau de l’hôte.

VM ou conteneur ?

VMConteneur
Isoleune machine complètedes processus
Noyaule siencelui de l’hôte
Systèmestout système (Windows, Linux, BSD…)même famille : conteneur Linux ⇒ noyau Linux
Démarragedizaines de secondesde l’ordre de la seconde
Tailleplusieurs Gode quelques Mo à quelques centaines
Isolementfortplus faible (noyau commun)
Pourtester un système, laboratoire, code douteuxlivrer une application et ses dépendances

Que choisir ?

  • Essayer un autre système, garder un poste propre → VM.
  • Laboratoire de sécurité, programme douteux → VM isolée, instantané, réseau coupé.
  • Faire tourner une application identique partout → conteneur.
  • Application + base de données + cache → Docker Compose.
  • Outils Linux sous Windows au quotidien → WSL 2.
  • Les deux se combinent : Docker dans une VM Linux est courant.

Se procurer ISO et images

  • ISO : site officiel du système, empreinte vérifiée.
  • Docker Hub : badges Docker Official Image et Verified Publisher ; regarder la date de mise à jour et le Dockerfile.
  • ! VM « toutes prêtes » (OVA) et images d’inconnus : porte dérobée ou mineur de cryptomonnaie possibles.
  • docker pull n’exécute rien ; docker run, si.

Vocabulaire

Hôtemachine physique et son système, qui accueille
Invitésystème qui tourne dans la VM
Hyperviseurlogiciel qui partage le matériel entre VM
Image ISOdisque d’installation d’un système
Disque virtuelfichier vu par l’invité comme un disque
Instantanéétat figé d’une VM, pour y revenir (snapshot)
Additions invitépilotes d’intégration hôte ↔ invité
Imagemodèle en lecture seule, en couches, d’où naissent les conteneurs
Conteneurinstance d’une image en cours d’exécution ; jetable
Couchestrate de fichiers d’une image, partagée entre images
Registreserveur d’images (Docker Hub, GitHub…)
Volumestockage qui survit au conteneur
Dockerfilerecette de construction d’une image
Composedescription de plusieurs conteneurs en YAML
VT-x / AMD-Vvirtualisation matérielle du processeur (Intel / AMD)
Émulationimiter un autre processeur (lent) ; la virtualisation exécute directement

Les hyperviseurs

Type 1sur le matériel, sans système hôteHyper-V, VMware ESXi, Xen, Proxmox VE (KVM)
Type 2application d’un système hôteVirtualBox, VMware Workstation, Parallels
KVMmodule du noyau Linux, piloté par QEMUsouvent classé type 1

Moteurs de conteneurs : Docker, Podman (sans démon), containerd ; orchestration à grande échelle : Kubernetes.

Règles d’or

  1. Un instantané avant toute expérience.
  2. Un instantané n’est pas une sauvegarde.
  3. Un conteneur est jetable : les données vont dans un volume.
  4. Fixer les versions : postgres:17, pas postgres:latest.
  5. Images officielles ou d’éditeurs vérifiés.
  6. Jamais de secret dans une image.

Sous Windows 11 Famille

  • VirtualBox : fonctionne (hyperviseur de type 2).
  • WSL 2 : disponible — un vrai noyau Linux dans une VM légère.
  • Hyper-V (gestionnaire) et Bac à sable Windows : réservés aux éditions Pro, Entreprise, Éducation.
  • Docker Desktop : les prérequis publiés citent Windows 11 Pro, Entreprise ou Éducation 23H2 ; une note y évoque les éditions Famille, limitées aux conteneurs Linux → à vérifier avant d’installer.
  • Solution sûre : Docker Engine dans une VM Linux.
  • ! Si WSL 2 est actif, VirtualBox passe par la plateforme de l’hyperviseur Windows : plus lent, parfois instable.

La virtualisation est-elle active ?

WindowsGestionnaire des tâches → Performances → Processeur → « Virtualisation : Activé »
Linuxgrep -Ec '(vmx|svm)' /proc/cpuinfo : résultat > 0 = processeur compatible
lsmod | grep kvm : module KVM chargé ?
Ubuntukvm-ok : diagnostic complet (paquet cpu-checker)

Désactivée ? Réglages UEFI (BIOS) au démarrage : Intel VT-x (« Virtualization Technology ») ou AMD-V (« SVM Mode »).

Repères (septembre 2026)

Docker Engine29.8.1 (15 septembre 2026) · libre (Apache 2.0)
Docker Desktopgratuit, sauf dans une entreprise de plus de 250 salariés ou de plus de 10 M$ de chiffre d’affaires : abonnement
VirtualBox7.2.20 · GPL v3 ; Extension Pack : licence PUEL, usage personnel et éducatif
WSL2.1.5 ou plus récent exigé par Docker Desktop

Versions vérifiées sur les sites officiels le 29 septembre 2026 : elles évoluent vite.

Processeur : PC ou ARM ?

  • VM et images visent une architecture : amd64 (x86-64, PC courants) ou arm64 (Mac à puce Apple, Raspberry Pi, certains portables).
  • Images multi-architectures : Docker choisit seul la bonne variante.
  • Architecture étrangère : émulation possible (QEMU), mais lente.
  • Connaître la sienne : uname -m (Linux) · $env:PROCESSOR_ARCHITECTURE (PowerShell).

2 · Machines virtuelles

Mémento — VM & Docker

Modes réseau d’une VM (noms de VirtualBox)

ModeInternetHôte → VMVM ↔ VMRéseau → VMUsage type
NAT (défaut)ouiredirection de portsnonnonnaviguer, installer ; l’invité est 10.0.2.15, l’hôte 10.0.2.2
Réseau NATouiredirection de portsouinonplusieurs VM qui se voient et sortent sur Internet
Accès par pontouiouiouiouiVM = une machine de plus sur le réseau local (adresse de la box)
Réseau privé hôtenonouiouinonserveur de test joignable depuis l’hôte seul (souvent 192.168.56.x)
Réseau internenonnonouinonlaboratoire de sécurité : VM isolées entre elles
Non connecténonnonnonnonanalyse d’un fichier suspect, hors ligne

Redirection NAT : port hôte 2222 → port invité 22, puis ssh -p 2222 utilisateur@127.0.0.1. ! En mode pont, la VM est exposée au réseau local comme un vrai poste : la mettre à jour.

Créer une VM : les étapes

  1. Télécharger l’image ISO sur le site officiel du système.
  2. Vérifier son empreinte : Get-FileHash f.iso (PowerShell) ou sha256sum f.iso, à comparer à celle publiée.
  3. Nouvelle machine : nom, type et version du système (64 bits).
  4. Mémoire vive, processeurs, disque virtuel (voir ci-dessous).
  5. Insérer l’ISO dans le lecteur optique virtuel, démarrer, installer.
  6. Mettre à jour l’invité, installer les additions invité.
  7. Éteindre proprement, prendre un instantané « propre ».

Dimensionner

MémoireLinux sans bureau : 1 à 2 Go · avec bureau : 4 Go · Windows 11 : 4 Go minimum ; laisser au moins la moitié à l’hôte
Processeurs2 suffisent souvent ; ne jamais dépasser le nombre de cœurs physiques
Disqueallocation dynamique ; 25 Go pour un Linux de bureau, 64 Go minimum pour Windows 11
Windows 11exige aussi TPM 2.0 et démarrage sécurisé (virtuels depuis VirtualBox 7)
Affichagemémoire vidéo au maximum si l’interface graphique rame

États et arrêt

Arrêt ACPIdemande polie : l’invité s’éteint proprement
Extinction forcée= débrancher la prise : risque de corruption
Enregistrer l’étatmet la VM en sommeil sur disque ; reprise à l’identique
Pausegèle la VM en mémoire

Additions invité et intégration

  • Apportent : écran redimensionnable, presse-papiers partagé, glisser-déposer, dossiers partagés, pilotes plus rapides.
  • VirtualBox : menu Périphériques → Insérer l’image CD des Additions invité ; sous Linux, installer d’abord les outils de compilation et les en-têtes du noyau.
  • Dossier partagé sous Linux : /media/sf_nom, accessible au groupe vboxsf : sudo usermod -aG vboxsf $USER, puis rouvrir la session.
  • Équivalents : open-vm-tools (VMware), qemu-guest-agent et spice-vdagent (KVM).
  • ! Presse-papiers, glisser-déposer et dossiers partagés percent l’isolement : les couper pour un laboratoire.

Échanger des fichiers avec la VM

  • Dossier partagé (additions invité) : le plus simple.
  • SSH par la redirection NAT : scp -P 2222 f utilisateur@127.0.0.1: (serveur SSH à installer dans l’invité : sudo apt install openssh-server).
  • Glisser-déposer, presse-papiers : pratiques au quotidien.
  • Clé USB attachée à la VM (menu Périphériques → USB) ou image ISO de fichiers.

Disques virtuels

VDIformat natif de VirtualBox
VMDKVMware ; lu aussi par VirtualBox et QEMU
VHD · VHDXHyper-V ; VHDX aussi pour le disque de WSL 2
qcow2QEMU / KVM : dynamique, instantanés internes
raw · imgimage brute, octet par octet
OVA · OVFmachine entière exportée (disques + réglages) : format d’échange entre hyperviseurs
Dynamiquegrossit à l’usage, ne rétrécit pas seul ; économe
Fixetaille réservée d’emblée ; un peu plus rapide

Convertir : qemu-img convert -f vmdk -O qcow2 a.vmdk b.qcow2. Agrandir le disque ne suffit pas : étendre ensuite la partition dans l’invité.

Instantané, clone, export, sauvegarde

Instantanéfige disque (et mémoire si la VM tourne) ; retour en quelques secondes ; dépend du disque d’origine
Clone completcopie indépendante de la VM
Clone liépartage le disque du parent : léger, mais inutilisable sans lui
Export OVAun seul fichier pour déplacer la VM vers un autre poste ou hyperviseur
Sauvegardecopie du dossier de la VM éteinte sur un autre support

! Un instantané n’est pas une sauvegarde : si le disque d’origine est perdu, l’instantané l’est aussi. Supprimer un instantané fusionne les différences sans toucher à l’état actuel. Éviter les longues chaînes.

Monter un laboratoire

  • Deux VM ou plus en réseau interne nommé (ex. labo) : elles se voient, et rien d’autre.
  • Pas de DHCP en réseau interne : adresses fixes (ex. 10.10.10.1, 10.10.10.2).
  • Besoin d’Internet pour installer ? Ajouter temporairement une 2e carte en NAT, puis la retirer.
  • ! Une machine volontairement vulnérable ne va jamais en mode pont.

Fichiers d’une VM (VirtualBox)

VirtualBox VMs/dans le dossier personnel ; un sous-dossier par VM
vm.vbox · vm.vdiréglages (XML) · disque virtuel
Snapshots/disques différentiels, états mémoire
Logs/VBox.logà lire quand la VM refuse de démarrer

! Déplacer, renommer : par VirtualBox, jamais à la main.

Une VM qui rame ?

  • Virtualisation matérielle activée (page 1) et additions invité installées.
  • Disque virtuel sur un SSD ; hôte pas à court de mémoire.
  • Ne pas surallouer : trop de processeurs ou de mémoire ralentit l’hôte… et la VM.
  • Invité Linux : carte réseau paravirtualisée (virtio-net).

3 · Outils : VirtualBox, KVM, WSL, Hyper-V

Mémento — VM & Docker

VirtualBox en ligne de commande : VBoxManage

Chaque commande ci-dessous commence par VBoxManage : VBoxManage list vms.

list vmsVM enregistrées (list runningvms : en marche)
list ostypesidentifiants de systèmes pour --ostype
showvminfo vmconfiguration complète
startvm vm --type headlessdémarrer sans fenêtre (serveur)
controlvm vm acpipowerbuttonarrêt propre
controlvm vm savestateenregistrer l’état et arrêter
controlvm vm poweroff! extinction forcée
controlvm vm pause · resumegeler · reprendre
Instantanés
snapshot vm take nomprendre (--description possible)
snapshot vm listlister
snapshot vm restore nomrevenir (VM éteinte)
snapshot vm delete nomsupprimer (fusion)
Cloner, déplacer, supprimer
clonevm vm --name copie --registerclone complet, enregistré
export vm -o vm.ovaexporter en OVA
import fichier.ovaimporter
unregistervm vm --delete! supprime la VM et ses disques
Réglages (VM éteinte)
modifyvm vm --memory 4096 --cpus 2mémoire en Mo, processeurs
modifyvm vm --nic1 natcarte 1 : nat, bridged, intnet, hostonly, natnetwork, none
modifyvm vm --nic1 intnet --intnet1 laboréseau interne nommé « labo »
modifyvm vm --natpf1 "ssh,tcp,,2222,,22"
redirection NAT : port 2222 de l’hôte → port 22 de l’invité
sharedfolder add vm --name nom --hostpath chemin --automount
dossier partagé, monté automatiquement
modifymedium disk f.vdi --compact
compacter un disque dynamique (après remise à zéro de l’espace libre dans l’invité)

Sous Windows, VBoxManage.exe se trouve dans C:\Program Files\Oracle\VirtualBox (souvent absent du PATH).

Créer une VM sans l’interface

# chaque ligne commence par VBoxManage
createvm --name labo --ostype Ubuntu_64 --register
modifyvm labo --memory 4096 --cpus 2 --nic1 nat
createmedium disk --filename labo.vdi --size 25600
storagectl labo --name SATA --add sata
storageattach labo --storagectl SATA --port 0 --device 0
    --type hdd --medium labo.vdi          # suite de la ligne
storageattach labo --storagectl SATA --port 1 --device 0
    --type dvddrive --medium systeme.iso  # suite
startvm labo

--size en Mo : 25600 = 25 Go. Identifiant exact du système : list ostypes.

Touche hôte de VirtualBox

Ctrl droittouche hôte : libère souris et clavier
Hôte+Fplein écran · Hôte+C mode redimensionné
Hôte+Supprenvoie Ctrl+Alt+Suppr à l’invité
Hôte+Tprendre un instantané
Hôte+Harrêt ACPI

KVM, QEMU, libvirt (hôte Linux)

virsh list --alltoutes les VM, allumées ou non
virsh start vmdémarrer
virsh shutdown vmarrêt propre (ACPI)
virsh destroy vm! extinction forcée — ne supprime rien, malgré le nom
virsh undefine vmretirer la VM ; disques conservés sauf --remove-all-storage
virsh autostart vmdémarrer avec l’hôte
virsh console vmconsole série ; sortir : Ctrl+]
virsh dominfo vmétat, mémoire, processeurs
virsh snapshot-create-as vm nominstantané
virsh snapshot-list vmlister
virsh snapshot-revert vm nomrevenir
virsh net-list --allréseaux virtuels
qemu-img create -f qcow2 d.qcow2 20Gcréer un disque de 20 Go
qemu-img info d.qcow2format, taille réelle et virtuelle
qemu-img resize d.qcow2 +10Gagrandir de 10 Go

Interface graphique : virt-manager. Gérer sans sudo : sudo usermod -aG libvirt $USER. Noms des paquets (QEMU, libvirt) : selon la distribution.

WSL 2 (PowerShell ou invite de commandes)

wsl --installinstaller WSL et Ubuntu (administrateur, redémarrage)
wsl -l -odistributions disponibles (--list --online)
wsl --install distributionen installer une autre
wsl -l -vinstallées, état, version 1 ou 2
wsl -d distributionouvrir une distribution précise
wsl --shutdownarrêter toutes les distributions et la VM
wsl -t distributionarrêter une distribution (--terminate)
wsl --export d f.tarsauvegarder une distribution
wsl --import nom dossier f.tarla restaurer ailleurs
wsl --unregister d! supprime la distribution et toutes ses données, sans retour
wsl --update · --version · --statusmettre à jour · versions · configuration
# %UserProfile%\.wslconfig — limiter la VM de WSL 2
[wsl2]
memory=4GB
processors=2

Appliquer : wsl --shutdown. Fichiers Windows vus de Linux : /mnt/c ; fichiers Linux vus de Windows : \\wsl.localhost\distribution. Travailler dans le système de fichiers Linux : bien plus rapide.

Hyper-V (Windows Pro, Entreprise, Éducation)

Get-VMlister les VM
Start-VM -Name vmdémarrer
Stop-VM -Name vmarrêt propre (-TurnOff : forcé)
Checkpoint-VM -Name vm -SnapshotName nompoint de contrôle (= instantané)
Restore-VMSnapshot -VMName vm -Name nomrevenir

Activation : Fonctionnalités de Windows → Hyper-V. Commandes PowerShell en administrateur.

4 · Docker : l’essentiel

Mémento — VM & Docker

Comment Docker fonctionne

Clientdocker …votre terminal
API→
Démon dockerdconstruit, lance, surveilleimages · conteneurs · volumes · réseaux
pull⇄push
RegistreDocker HubGHCR, registre privé…
  • docker build : Dockerfile → image · docker pull : registre → image locale · docker run : image → conteneur.
  • Image = modèle en lecture seule ; conteneur = image + une couche inscriptible, effacée avec lui.
  • Sous le démon : containerd gère les conteneurs, runc les crée à l’aide du noyau (espaces de noms, cgroups).
  • Docker Desktop (Windows, macOS) = démon dans une VM Linux + interface graphique.

Les briques d’un conteneur Linux

Espaces de nomsce que le processus voit : ses processus, son réseau, ses montages, son nom d’hôte
Groupes de contrôlece qu’il peut consommer : mémoire, processeur, disque, nombre de processus (cgroups)
Capacitésles pouvoirs de root découpés ; Docker n’en laisse qu’une partie
seccomp, AppArmor, SELinuxfiltrent les appels système et les accès
Couches (OverlayFS)image en lecture seule, partagée + couche inscriptible propre au conteneur

Aucune « machine » : un conteneur est un processus ordinaire de l’hôte, simplement cloisonné.

Anatomie de docker run

docker runcommande
-den arrière-plan
--name webnom
-p 8080:80port hôte:conteneur
nginx:alpineimage:étiquette

Puis ouvrir http://localhost:8080. Tout ce qui suit l’image remplace sa commande par défaut : docker run --rm alpine ls /etc.

Options essentielles de docker run

-ddétaché (arrière-plan) ; affiche l’identifiant
-itinteractif avec terminal : docker run -it alpine sh
--rmsupprimer le conteneur à l’arrêt
--name nomnom lisible (sinon nom aléatoire)
-p 8080:80publier : port 8080 de l’hôte → 80 du conteneur
-p 127.0.0.1:8080:80publier pour l’hôte seulement
-e VAR=valeurvariable d’environnement (--env-file f)
-v volume:/cheminmonter un volume nommé
-v "$(pwd)":/appmonter le dossier courant (Bash)
-w /appdossier de travail
--restart unless-stoppedrelancer après panne ou redémarrage
--memory 512m --cpus 1.5limiter mémoire et processeur
--user 1000:1000s’exécuter sans être root
--network réseaurejoindre un réseau
--entrypoint shremplacer le point d’entrée

Formes longues équivalentes : docker container run = docker run, docker container ls = docker ps, docker image ls = docker images.

Cycle de vie d’un conteneur

imagecreate→crééstart→en marchestop→arrêtérm→supprimé
docker run= create + start
docker stop csignal SIGTERM, puis SIGKILL après 10 s
docker kill carrêt immédiat (SIGKILL)
docker start · restart crelancer un conteneur arrêté
docker pause · unpause cgeler · reprendre
docker rm csupprimer un conteneur arrêté (-f : même en marche)

Un conteneur vit tant que son processus principal vit : si ce processus se termine, le conteneur s’arrête.

Observer et intervenir

docker psconteneurs en marche (-a : tous)
docker logs -f --tail 100 csuivre le journal (--since 10m)
docker exec -it c shouvrir un shell dans un conteneur en marche (bash s’il existe)
docker statsprocesseur, mémoire, réseau en direct
docker top cprocessus du conteneur
docker inspect ctout le détail en JSON
docker inspect -f '{{.State.Status}}' cextraire un champ
docker port cports publiés
docker cp c:/chemin ./copier depuis (ou vers) un conteneur
docker diff cfichiers modifiés depuis l’image
docker eventsévénements du démon en direct

Premiers pas

docker run hello-world
docker run -it --rm alpine sh        # shell jetable
docker run -d --name web -p 8080:80 nginx:alpine
docker ps                            # web est « Up »
docker logs web                      # journal d’accès
docker stop web && docker rm web     # ménage

Installer et vérifier

Linuxdépôt officiel de Docker, puis paquets docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin, docker-compose-plugin
sudo docker run hello-worldtest : télécharge et lance une image d’essai
docker version · infoversions du client et du démon · configuration
sudo systemctl enable --now dockerdémarrer le démon, et à chaque démarrage

! Désinstaller d’abord les paquets non officiels (docker.io, podman-docker…). Le script get.docker.com : réservé aux essais, pas à la production.

Filtrer et formater

docker ps -qidentifiants seuls
docker ps -a -f status=exitedfiltrer : conteneurs arrêtés
docker ps -f name=webfiltrer par nom
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
colonnes choisies
docker stop $(docker ps -q)arrêter tout ce qui tourne (Bash)

Un préfixe unique de l’identifiant suffit : docker stop 3f2a.

5 · Images et Dockerfile

Mémento — VM & Docker

Nom complet d’une image

docker.io/registre
library/espace de noms
postgresdépôt
:17étiquette
@sha256:…empreinte
  • Registre par défaut : Docker Hub · espace library = images officielles.
  • Sans étiquette : latest — ce n’est pas forcément la plus récente, juste l’étiquette par défaut.
  • L’empreinte @sha256: désigne un contenu immuable ; une étiquette peut être déplacée.

Gérer les images

docker pull image:tagtélécharger
docker imagesimages locales (docker image ls)
docker images -f dangling=trueimages « pendantes », sans nom
docker rmi imagesupprimer (si aucun conteneur ne l’utilise)
docker tag src registre/nom:tagdonner un autre nom
docker login registres’authentifier (Docker Hub par défaut)
docker push registre/nom:tagpublier
docker history imagecouches et instructions qui les ont créées
docker save -o f.tar imageexporter une image dans un fichier…
docker load -i f.tar… et la charger sur une autre machine
docker search motchercher sur Docker Hub

! docker export / import travaillent sur un conteneur : système de fichiers aplati, sans couches ni réglages. docker commit fige un conteneur bricolé à la main : préférer un Dockerfile, reproductible.

Un Dockerfile commenté

# syntax=docker/dockerfile:1
FROM python:3.14-slim          # base officielle, version fixée
WORKDIR /app                   # dossier de travail
COPY requirements.txt .        # 1. les dépendances…
RUN pip install --no-cache-dir -r requirements.txt
COPY . .                       # 2. …puis le code
RUN useradd --create-home appli
USER appli                     # ne pas rester root
ENV PORT=8000
EXPOSE 8000                    # documente le port
CMD ["python", "app.py"]       # commande par défaut
docker build -t appli:1.0 .construire ; le . final = contexte envoyé au démon
-f autre.Dockerfileautre fichier que Dockerfile
--no-cachetout reconstruire
--build-arg VAR=valvaleur d’un ARG
--target étapes’arrêter à une étape nommée
--platform linux/amd64architecture visée (PC ou ARM)

Publier une image

docker login                      # Docker Hub
docker tag appli:1.0 compte/appli:1.0
docker push compte/appli:1.0

Autre registre : préfixer par son adresse, registre/appli:1.0. ! Un dépôt public est visible de tous.

Tester la santé d’un service

HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD curl -fs http://localhost:8000/ || exit 1

docker ps affiche alors (healthy), (unhealthy) ou (health: starting). ! L’outil appelé (curl) doit exister dans l’image.

Instructions

FROMimage de départ ; FROM … AS nom nomme une étape
RUNexécute une commande à la construction ; crée une couche
COPYcopie depuis le contexte (--chown=u:g)
ADDcomme COPY + archives et URL : préférer COPY
WORKDIRdossier courant des instructions suivantes
ENVvariable conservée dans l’image
ARGvariable de construction seulement
EXPOSEdocumente un port ; ne publie rien
USERutilisateur des instructions suivantes et du conteneur
VOLUMEpoint de montage prévu pour des données
ENTRYPOINTprogramme toujours lancé
CMDcommande ou arguments par défaut
HEALTHCHECKtest de bonne santé périodique
LABELmétadonnées : auteur, version, licence

CMD, ENTRYPOINT et leurs formes

CMD ["app", "-v"]forme exec (JSON) : le programme est le processus 1 et reçoit les signaux → à préférer
CMD app -vforme shell : lancé par /bin/sh -c ; ! docker stop attend souvent les 10 s
ENTRYPOINT + CMDENTRYPOINT ["ping"] + CMD ["localhost"] ; docker run img exemple.org remplace seulement CMD

Couches et cache

  • Chaque instruction produit une couche ; si l’une change, toutes les suivantes sont reconstruites.
  • Ordre : ce qui change rarement en haut (système, dépendances), le code en bas.
  • Installer et nettoyer dans la même couche, sinon les fichiers supprimés pèsent encore :
RUN apt-get update \
 && apt-get install -y --no-install-recommends curl \
 && rm -rf /var/lib/apt/lists/*

Construction en plusieurs étapes

FROM node:22 AS build          # 1. outils complets
WORKDIR /src
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build              # produit /src/dist
FROM nginx:alpine              # 2. image finale légère
COPY --from=build /src/dist /usr/share/nginx/html

L’image finale ne contient que le résultat : ni compilateur, ni sources, ni dépendances de développement.

.dockerignore et bonnes pratiques

.git
node_modules
*.log
.env                 # secrets : jamais dans le contexte
  • Image de base officielle et minimale (-slim, alpine, distroless), version fixée.
  • Un processus principal par conteneur.
  • ! Aucun secret dans l’image : ENV, ARG et fichiers copiés restent lisibles (docker history, couches).
  • Utilisateur non root ; HEALTHCHECK pour les services.

6 · Données et réseau

Mémento — VM & Docker

Où vivent les données ?

TypePrincipePour
Volume nommégéré par Docker, hors du conteneur ; survit à docker rmdonnées d’une base, fichiers d’une application
Montage lié (bind)un dossier de l’hôte vu dans le conteneurdéveloppement : code source édité sur l’hôte
tmpfsen mémoire vive, effacé à l’arrêt (Linux)fichiers temporaires, sensibles
Couche du conteneurécrite dans le conteneur lui-même! perdue avec docker rm

Syntaxes

-v donnees:/var/lib/datavolume nommé (créé s’il n’existe pas)
-v /srv/site:/site:romontage lié, en lecture seule
-v "$(pwd)":/appdossier courant · PowerShell : "${PWD}:/app"
--mount type=volume,src=donnees,dst=/data
forme longue, explicite
--mount type=bind,src=/srv/site,dst=/site
montage lié ; refuse un chemin d’hôte absent
--tmpfs /tmpdossier temporaire en mémoire
  • -v crée silencieusement un dossier d’hôte absent (appartenant à root) ; --mount signale l’erreur.
  • Un volume nommé vide reçoit le contenu du dossier de l’image ; un montage lié le masque.
  • Droits : le conteneur écrit avec son identifiant (UID) ; aligner avec --user.

Gérer les volumes

docker volume create vcréer
docker volume lslister
docker volume inspect vemplacement réel (Mountpoint)
docker volume rm v! supprimer, avec les données
docker volume prunevolumes anonymes inutilisés
docker volume prune -a! tous les volumes inutilisés

Sauvegarder et restaurer un volume

# sauvegarde : archive dans le dossier courant
docker run --rm -v donnees:/source:ro \
  -v "$(pwd)":/sauv alpine \
  tar czf /sauv/donnees.tar.gz -C /source .
# restauration dans un volume (vide)
docker run --rm -v donnees:/cible \
  -v "$(pwd)":/sauv alpine \
  tar xzf /sauv/donnees.tar.gz -C /cible

Arrêter d’abord le conteneur qui écrit dans le volume. Pour une base de données, préférer son outil d’export (pg_dump, mysqldump).

Réglages du démon : /etc/docker/daemon.json

{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" },
  "data-root": "/srv/docker",
  "default-address-pools": [
    { "base": "10.200.0.0/16", "size": 24 } ]
}
  • ! Journaux json-file sans rotation par défaut : un conteneur bavard remplit le disque. Les options valent pour les conteneurs créés ensuite.
  • data-root : déplacer le stockage de Docker ; default-address-pools : si 172.17.x.x entre en conflit avec le réseau local.
  • Appliquer : sudo systemctl restart docker · Docker Desktop : Settings → Docker Engine.

Pilotes de réseau

bridge (défaut)réseau privé sur l’hôte ; ports publiés avec -p
bridge défini par l’utilisateuridem + résolution par nom : db, cache… → à utiliser
hostpartage la pile réseau de l’hôte, sans isolement (Linux)
noneaucun réseau
overlayréseau commun à plusieurs hôtes (Swarm)
macvlanadresse propre sur le réseau local, comme une machine physique

Commandes réseau

docker network lslister
docker network create rcréer un réseau bridge
docker run --network r …lancer dans ce réseau
docker network connect r cbrancher un conteneur existant
docker network inspect rconteneurs et adresses
docker network rm · prunesupprimer un réseau · les inutilisés
docker network create appnet
docker run -d --name cache --network appnet redis:alpine
docker run -it --rm --network appnet redis:alpine \
  redis-cli -h cache ping          # → PONG

Le nom du conteneur (cache) sert de nom d’hôte. Sur le réseau bridge par défaut, cette résolution ne fonctionne pas.

Publier un port

navigateurlocalhost:8080→hôte-p 8080:80→conteneur :80
-p 8080:80toutes les interfaces de l’hôte (0.0.0.0 et [::]) : visible du réseau
-p 127.0.0.1:8080:80depuis l’hôte seulement
-p 5353:53/udpport UDP
-Ptous les ports EXPOSE vers des ports hôte au hasard
  • ! Linux : les ports publiés contournent le pare-feu ufw ; publier sur 127.0.0.1 ce qui ne doit pas sortir.
  • Dans un conteneur, localhost = le conteneur lui-même, pas l’hôte.
  • Joindre l’hôte : host.docker.internal (Docker Desktop ; sous Linux : --add-host=host.docker.internal:host-gateway).
  • Entre conteneurs d’un même réseau : le port interne (db:5432), sans publication.

Diagnostiquer le réseau

docker port cpublications effectives
docker network inspect rqui est branché, avec quelle adresse
docker exec c getent hosts dble nom db se résout-il ? (ou nslookup db, selon l’image)
docker exec c wget -qO- http://web:8000le service répond-il ? (curl s’il existe)
sudo ss -tlnphôte Linux : quel programme écoute sur quel port ?
docker run --rm -it --network container:c alpine sh
shell de dépannage dans la pile réseau du conteneur, quand son image n’a aucun outil

Où Docker range tout

  • Linux : /var/lib/docker — images, conteneurs, volumes. ! N’y rien modifier à la main.
  • Docker Desktop : dans le disque virtuel de sa VM.
  • docker system df -v : détail par image, conteneur, volume.
  • ~/.docker/config.json : réglages du client ; ! docker login y range les identifiants simplement encodés, sans chiffrement, faute d’assistant d’identifiants (credential helper).

7 · Docker Compose

Mémento — VM & Docker

Un compose.yaml commenté

services:
  web:                          # nom du service = nom d’hôte
    build: .                    # image construite ici
    ports:
      - "127.0.0.1:8000:8000"
    environment:
      DB_HOST: db               # le service « db »
    env_file: .env              # variables injectées
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:17          # version fixée
    environment:
      POSTGRES_USER: appli
      POSTGRES_DB: appli
      POSTGRES_PASSWORD_FILE: /run/secrets/db_mdp
    secrets: [db_mdp]
    volumes:
      - donnees:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appli"]
      interval: 5s
      retries: 5

volumes:
  donnees:                      # volume nommé

secrets:
  db_mdp:
    file: ./db_mdp.txt          # hors dépôt Git !

Le mot de passe est lu dans un fichier monté en /run/secrets/, pas écrit en clair dans le YAML. ! YAML : indentation par espaces (jamais de tabulation) ; mettre les ports entre guillemets.

Démarrer dans l’ordre

  • depends_on seul garantit l’ordre de lancement, pas que le service soit prêt.
  • Avec condition: service_healthy, Compose attend que le healthcheck du service réussisse.
  • L’application doit tout de même savoir réessayer une connexion perdue.

De docker run à Compose

docker runcompose.yaml
-p 8080:80ports: ["8080:80"]
-v donnees:/datavolumes: ["donnees:/data"] + section volumes:
-e VAR=valenvironment: puis VAR: val
--env-file .envenv_file: .env
--restart unless-stoppedrestart: unless-stopped
--network appnetnetworks: [appnet]
--memory 512mmem_limit: 512m
--name webcontainer_name: web (rarement utile)
image cmdcommand: cmd

Mettre à jour l’application

docker compose pull          # nouvelles images
docker compose up -d         # recrée ce qui a changé
docker image prune           # anciennes images
  • Lire les notes de version ; sauvegarder les volumes avant.
  • ! Base de données : changer de version majeure (PostgreSQL 17 → 18) exige une migration des données.
  • Image construite localement : docker compose up -d --build.

Principe

  • Un fichier décrit toute l’application : services, réseaux, volumes, secrets.
  • Nom par défaut : compose.yaml (préféré) ; docker-compose.yml reste lu.
  • Commande actuelle : docker compose (avec une espace) ; l’ancien docker-compose (tiret) est obsolète.
  • La clé version: en tête de fichier est obsolète : Compose l’ignore et avertit.
  • Un réseau projet_default relie les services : chacun joint les autres par son nom.
  • Projet = nom du dossier, préfixe des conteneurs et volumes (-p nom pour le changer).

Commandes

Chaque commande commence par docker compose : docker compose up -d.

up -dcréer et démarrer en arrière-plan
up -d --buildreconstruire les images d’abord
psétat des services
logs -f servicesuivre les journaux
exec service shshell dans un service en marche
run --rm service cmdtâche ponctuelle dans un conteneur neuf
restart serviceredémarrer
stop · startarrêter · relancer sans supprimer
pullmettre à jour les images
configfichier final, variables résolues : valider
downsupprimer conteneurs et réseau ; volumes gardés
down -v! supprime aussi les volumes : données perdues
-f f.yaml …utiliser un autre fichier

Clés utiles d’un service

image · buildimage existante · à construire (build: ./dossier)
portspublication "hôte:conteneur"
volumesvolume nommé ou montage lié ./src:/app
environment · env_filevariables · fichier de variables
depends_onordre de démarrage (+ condition)
healthchecktest de santé
restartno, always, on-failure, unless-stopped
command · entrypointremplacer CMD · ENTRYPOINT
networksréseaux rejoints
profilesservice facultatif : docker compose --profile p up
deploy.resourceslimites de mémoire et de processeur

Variables et fichiers

  • .env du dossier du projet : lu automatiquement pour remplacer ${VAR} dans le YAML.
  • ${VAR:-défaut} valeur par défaut · ${VAR:?message} erreur si absente.
  • env_file: injecte des variables dans le conteneur : ce n’est pas le même mécanisme.
  • compose.override.yaml, s’il existe, est fusionné automatiquement : réglages de développement.
  • ! .env et fichiers de secrets : dans .gitignore et .dockerignore.

8 · Sécurité, ménage, dépannage

Mémento — VM & Docker

Durcir un conteneur

--user 1000:1000ne pas tourner en root
--read-only --tmpfs /tmpsystème de fichiers en lecture seule
--cap-drop ALLretirer les privilèges du noyau (--cap-add au cas par cas)
--security-opt no-new-privilegesinterdire l’élévation (setuid)
--memory · --cpus · --pids-limitborner les ressources
-p 127.0.0.1:…ne rien exposer sans raison
--network nonecouper le réseau
  • ! Jamais --privileged ni -v /var/run/docker.sock:… sans comprendre : c’est donner l’hôte.
  • ! Le groupe docker donne des droits équivalents à root sur l’hôte (documentation officielle). Alternatives : mode rootless, Podman.
  • Images officielles ou d’éditeurs vérifiés ; version fixée ; les mettre à jour ; analyser les vulnérabilités (docker scout cves image, Trivy, Grype).
  • Secrets : fichiers montés (secrets:), jamais dans l’image ni dans le dépôt.

Exécuter un programme douteux

  1. VM dédiée, jamais le poste principal ni un conteneur : le noyau partagé rend l’évasion plus plausible.
  2. Instantané propre avant, retour à cet instantané après.
  3. Réseau interne ou non connecté ; pas de dossier partagé, de presse-papiers ni de glisser-déposer.
  4. ! WSL n’est pas une frontière de sécurité : Linux y lit et écrit les fichiers Windows (/mnt/c).
  5. Idéalement : inspection du code avant toute exécution.

Sécurité des VM

  • Mettre à jour l’hyperviseur : des failles d’évasion de VM existent.
  • Un instantané pris VM allumée contient la mémoire : mots de passe, clés… le protéger comme la VM.
  • Données sensibles : chiffrer le disque dans l’invité (LUKS, BitLocker).
  • N’importer que des OVA de source sûre ; couper dossiers partagés, presse-papiers et USB quand ils ne servent pas.

Service en production : liste de contrôle

  1. Image à version fixée, base officielle, reconstruite régulièrement.
  2. Utilisateur non root, privilèges retirés (--cap-drop).
  3. healthcheck et restart: unless-stopped.
  4. Limites de mémoire et de processeur ; journaux bornés (max-size).
  5. Ports liés à 127.0.0.1, derrière un proxy inverse en HTTPS.
  6. Volumes sauvegardés et restauration testée.
  7. Secrets hors de l’image et du dépôt ; mises à jour surveillées.

Docker ↔ Podman

  • Mêmes commandes : podman run, podman ps, podman build… (alias docker=podman).
  • Sans démon et sans root par défaut ; notion de pod (groupe de conteneurs).
  • ! Donner les noms d’images complets : docker.io/library/nginx:alpine.

Pour aller plus loin

  • docs.docker.com : guides, référence de la CLI, de Compose et du Dockerfile.
  • virtualbox.org/manual : manuel de VirtualBox, dont VBoxManage.
  • learn.microsoft.com/windows/wsl : WSL.
  • libvirt.org · qemu.org : KVM et QEMU.
  • Pratiquer : tout refaire dans une VM jetable, instantané à l’appui.

Faire le ménage

docker system dfespace occupé : images, conteneurs, volumes, cache
docker container pruneconteneurs arrêtés
docker image pruneimages pendantes (-a : toutes les inutilisées)
docker builder prunecache de construction
docker volume prunevolumes anonymes (-a : tous les inutilisés)
docker system pruneconteneurs arrêtés, réseaux inutilisés, images pendantes, cache
docker system prune -a --volumes! grand ménage ; volumes nommés épargnés

Tout prune demande confirmation ; -f la saute. Lire la liste avant de valider.

Messages fréquents

permission denied while trying to connect to the Docker daemon socketutilisateur hors du groupe docker : sudo, ou ajout au groupe puis nouvelle session
Cannot connect to the Docker daemon … Is the docker daemon running?démon arrêté : sudo systemctl start docker, ou lancer Docker Desktop
port is already allocatedport de l’hôte déjà pris : en choisir un autre
Conflict. The container name "/web" is already in usedocker rm web ou autre --name
pull access denied … repository does not existnom mal orthographié ou image privée (docker login)
no space left on devicedocker system df, puis ménage
exec format errorimage d’une autre architecture (ARM ↔ PC) : --platform
VT-x is disabled in the BIOS · 0x80370102 (WSL)virtualisation matérielle désactivée : l’activer dans l’UEFI

Codes de sortie d’un conteneur

0fin normale
1erreur de l’application : lire docker logs
125docker run lui-même a échoué (option, image)
126 · 127commande non exécutable · introuvable
137tué par SIGKILL (128 + 9) : souvent mémoire dépassée → docker inspect -f '{{.State.OOMKilled}}' c
143arrêté par SIGTERM (128 + 15), par exemple docker stop

Démarche : docker ps -a → docker logs → docker inspect → docker exec -it c sh ; conteneur qui s’arrête aussitôt : docker run -it --rm --entrypoint sh image pour regarder dedans.

Glossaire anglais → français

bind mountmontage liélayercouche
bridgedaccès par pontlinked cloneclone lié
build contextcontextenamespaceespace de noms
checkpointpoint de contrôleprunepurger
dangling imageimage pendanteregistryregistre
digestempreinterestart policypolitique de redémarrage
guest additionsadditions invitérootlesssans root
headlesssans fenêtresnapshotinstantané
health checktest de santétagétiquette
host-onlyréseau privé hôtevolumevolume