Un volume qu'aucun conteneur n'utilise est dit orphelin pour Docker, mais cela ne prouve pas qu'il est inutile : il peut porter la base d'un projet que vous avez arrêté ou renommé. Cette leçon vous apprend à retrouver ce volume parmi d'autres, à lire son contenu sans rien risquer, à en garder une copie qui se relit, à le rattacher à un service Compose sans le recréer, puis à supprimer seulement ce qui est jetable. Les mesures viennent d'une VM Debian 13 avec Docker Engine 29.9.2 et Compose 5.6.1.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »Chaque geste se vérifie sur l'état réel du moteur, pas sur une supposition.
- Vous distinguez un volume nommé d'un volume anonyme, et vous savez ce que
docker rm,docker rm -vetdocker run --rmen font. - Vous retrouvez un volume par ses labels, son nom ou son conteneur, et vous lisez son contenu par un conteneur jetable monté en lecture seule.
- Vous sauvegardez un volume avec
tar, puis vous relisez l'archive avant de rien supprimer. - Vous rattachez l'ancien volume d'un projet Compose renommé avec
external: true, sans le recréer. - Vous prévoyez ce que retirent
docker volume pruneetdocker compose down -v, et vous supprimez un volume par son nom seulement.
Prérequis
Section intitulée « Prérequis »Vous devez savoir créer un volume nommé, voir la différence avec un volume
anonyme et le filtrer avec dangling=true : la leçon
Volumes Docker : conserver ses données et monter des fichiers
l'explique. Vous devez aussi connaître le nom de projet Compose et l'effet de
down -v, présentés dans
Persister les données d'une stack recréée.
Pour sauvegarder la base d'une stack Compose par un export logique plutôt que
par une copie du volume, le guide
Sauvegarder et restaurer une application
prend le relais.
Jouez les blocs dans l'ordre et dans un même terminal : ils réutilisent la
variable IMAGE et le dossier courant. Tous les objets de la démonstration
portent le préfixe c41b-m-, ce qui permet de ne cibler qu'eux. Ne jouez
pas cette leçon sur un hôte qui porte des volumes à vous : docker volume ls
y montrerait aussi vos volumes, et vous risqueriez de les confondre avec ceux
de la démonstration.
export IMAGE="alpine:3.24.3@sha256:be2656061b536c1883c4034790e21d0a09c5aaaf51968b89368a3c0371ea2c9a"mkdir -p ~/donnees-orphelines/ctx ~/donnees-orphelines/projetcd ~/donnees-orphelinesdocker volume lsDRIVER VOLUME NAMELa liste est vide sur la VM de mesure. Si la vôtre contient déjà des volumes, notez-les pour vérifier à la fin qu'ils n'ont pas bougé, mais préférez une VM jetable.
Qu'est-ce qu'un volume orphelin, et pourquoi n'est-il pas forcément inutile ?
Section intitulée « Qu'est-ce qu'un volume orphelin, et pourquoi n'est-il pas forcément inutile ? »Un volume est orphelin quand aucun conteneur ne le référence, même arrêté.
Docker le liste avec le filtre dangling=true, qui regroupe les volumes nommés
et les volumes anonymes sans distinction. Ce filtre dit seulement qu'aucun
conteneur ne l'utilise : il ne dit rien sur la valeur de ce qu'il contient.
Un volume nommé porte le nom que vous lui donnez, par exemple
docker volume create c41b-m-data. Un volume anonyme naît sans nom, quand un
conteneur déclare un chemin sans source ou quand l'image déclare une instruction
VOLUME : Docker lui donne alors un nom de 64 caractères hexadécimaux. Le
Dockerfile suivant déclare VOLUME /donnees, après avoir écrit un fichier dans
ce dossier.
cat > ctx/Dockerfile <<EOFFROM $IMAGERUN mkdir /donnees && echo graine > /donnees/graine.txtVOLUME /donneesCMD ["sleep","300"]EOFdocker build -q -t c41b-m-img:1 ctxdocker run -d --name c41b-m-v1 c41b-m-img:1ANON=$(docker inspect -f '{{range .Mounts}}{{.Name}}{{end}}' c41b-m-v1)docker volume lssha256:3e5fd844868389b03664723cfcd37d39ecc4aa0f667dde67e8bd4314e260ed9bfb988cb1a0266f90a6f3b50c5e2dbfed6be3050b600e77a7760f7e6cdcdf8d7bDRIVER VOLUME NAMElocal 7eecf463ce016e35092868234b465ae42e53e9c80d58b32db65843383677c0d6Dans la dernière sortie, regardez le nom : 64 caractères hexadécimaux, aucun
nom lisible. docker run a créé ce volume tout seul, et la variable ANON en
garde le nom pour la suite. Ce qui était écrit dans /donnees avant VOLUME
est copié dans le volume au premier démarrage : graine.txt s'y retrouve plus
bas.
docker volume inspect confirme son origine : le label
com.docker.volume.anonymous marque un volume anonyme, et CreatedAt donne sa
date de création en UTC.
docker volume inspect "$ANON"[ { "CreatedAt": "2026-11-04T18:32:38Z", "Driver": "local", "Labels": { "com.docker.volume.anonymous": "" }, "Mountpoint": "/var/lib/docker/volumes/7eecf463ce016e35092868234b465ae42e53e9c80d58b32db65843383677c0d6/_data", "Name": "7eecf463ce016e35092868234b465ae42e53e9c80d58b32db65843383677c0d6", "Options": null, "Scope": "local" }]Un montage sans nom, comme -v /donnees2, a donné le même résultat : un volume
de 64 caractères hexadécimaux. Le guide
Volumes Docker montre
déjà comment repérer et supprimer un anonyme ; cette leçon s'intéresse à ce
qu'on en fait quand on ne sait plus à quoi il servait.
Que devient un volume anonyme quand on supprime son conteneur ?
Section intitulée « Que devient un volume anonyme quand on supprime son conteneur ? »Supprimer un conteneur avec docker rm laisse son volume anonyme en place.
Le volume devient alors orphelin : il apparaît avec dangling=true, et rien ne
le supprimera tant que vous ne le demandez pas. Pour retirer le volume avec le
conteneur, il faut l'option -v, ou lancer le conteneur avec --rm.
Le tableau ci-dessous résume ce que chaque geste laisse. La démonstration
supprime c41b-m-v1 sans -v et vérifie que son volume reste, orphelin : elle
sert aussi de base aux sections suivantes.
| Geste | Volume anonyme du conteneur |
|---|---|
docker rm ou docker rm -f | reste, orphelin |
docker rm -v ou docker rm -fv | supprimé avec le conteneur |
docker run --rm | supprimé quand le conteneur s'arrête |
docker rm -f c41b-m-v1docker volume ls --filter dangling=truec41b-m-v1DRIVER VOLUME NAMElocal 7eecf463ce016e35092868234b465ae42e53e9c80d58b32db65843383677c0d6Tant que c41b-m-v1 existait, il référençait son volume, qui n'était donc pas
orphelin. Après docker rm -f, le volume apparaît dans la liste, comme le dit
la première ligne du tableau. Avec -v ou --rm, le volume part avec le
conteneur.
Un conteneur arrêté, et même un conteneur seulement créé sans jamais
démarrer, garde son volume référencé. Le test ci-dessous crée un conteneur
depuis l'image qui déclare VOLUME, le laisse s'arrêter, puis liste les volumes
encore référencés avec dangling=false.
docker run --name c41b-m-v3 c41b-m-img:1 truedocker volume ls --filter dangling=falsedocker rm -v c41b-m-v3DRIVER VOLUME NAMElocal 6b739925f13f30bf22dfdc4aa3b64984bc6d37d67ae7a95d94284406cbba421fc41b-m-v3Le volume de c41b-m-v3 figure sous dangling=false parce que le conteneur
arrêté existe encore. Retenez-le : un volume « non monté » peut être encore
référencé, et c'est tant mieux, puisque docker volume rm le refuse alors.
Comment retrouver le bon volume parmi plusieurs ?
Section intitulée « Comment retrouver le bon volume parmi plusieurs ? »Un volume se retrouve par ses labels, par son nom ou par le conteneur qui le référence. Les labels sont le repère le plus direct, mais ils n'existent que si vous les avez posés à la création : un volume sans label ne se distingue que par son nom ou sa date. La démonstration crée donc trois volumes nommés, dont un sans label, et écrit des données dans le premier.
docker volume create --label c41b-m-test=1 --label c41b-m-role=donnees c41b-m-datadocker volume create --label c41b-m-test=1 --label c41b-m-role=jetable c41b-m-jetabledocker volume create c41b-m-sanslabeldocker run --rm -v c41b-m-data:/d "$IMAGE" \ sh -c 'echo commande-42 > /d/recu.txt; mkdir /d/sub; echo x > /d/sub/a'docker volume ls --filter dangling=truec41b-m-datac41b-m-jetablec41b-m-sanslabelDRIVER VOLUME NAMElocal 7eecf463ce016e35092868234b465ae42e53e9c80d58b32db65843383677c0d6local c41b-m-datalocal c41b-m-jetablelocal c41b-m-sanslabelLes quatre volumes sont orphelins, nommés ou non, et la liste ne dit pas
lequel porte des données. Le filtre label fait le tri. Une clé seule, ou une
paire clé=valeur, fonctionne, et deux filtres label se combinent en ET.
docker volume ls --filter dangling=true --filter label=c41b-m-testdocker volume ls --filter label=c41b-m-role=jetabledocker volume ls --filter label=c41b-m-test=1 --filter label=c41b-m-role=donneesDRIVER VOLUME NAMElocal c41b-m-datalocal c41b-m-jetableDRIVER VOLUME NAMElocal c41b-m-jetableDRIVER VOLUME NAMElocal c41b-m-dataLe filtre name accepte une sous-chaîne du nom : --filter name=c41b-m-
a trouvé les trois volumes nommés. Le gabarit --format affiche les labels sous
la forme clé=valeur,clé=valeur. Un volume sans label s'y reconnaît à sa
colonne vide.
docker volume ls --filter dangling=true --filter name=c41b-m- \ --format '{{.Name}}|{{.Labels}}'c41b-m-data|c41b-m-role=donnees,c41b-m-test=1c41b-m-jetable|c41b-m-role=jetable,c41b-m-test=1c41b-m-sanslabel|Pour lire une valeur précise, docker volume inspect --format '{{json .Labels}}'
rend un objet JSON.
L'autre entrée est le conteneur. docker ps -a --filter volume= liste les
conteneurs, arrêtés ou seulement créés, qui référencent un volume ; la sortie
est vide quand aucun ne le fait. Pour le voir, créez un conteneur qui monte
c41b-m-data sur /lu en lecture seule, sans le démarrer.
docker create --name c41b-m-user -v c41b-m-data:/lu:ro "$IMAGE" sleep 300docker ps -a --filter volume=c41b-m-data --format '{{.Names}} {{.Status}}'docker ps -a --filter volume=c41b-m-jetable --format '{{.Names}} {{.Status}}'docker ps -a --filter volume=/lu --format '{{.Names}}'5939ba135634f49dd570b7b35b2cffb2f1e9bf3a74efc0aefa5405e198d84045c41b-m-user Createdc41b-m-userLa première commande trouve le conteneur, même au statut Created. La
deuxième ne rend rien : aucun conteneur ne référence c41b-m-jetable. La
troisième montre que le filtre accepte aussi un point de montage (/lu).
Dès que ce conteneur existe, c41b-m-data passe de dangling=true à
dangling=false, et docker volume rm refuse de le supprimer.
docker volume rm c41b-m-dataError response from daemon: remove c41b-m-data: volume is in use - [5939ba135634f49dd570b7b35b2cffb2f1e9bf3a74efc0aefa5405e198d84045]Ce refus est une protection : le moteur ne supprime pas un volume référencé, même par un conteneur qui ne tourne pas. Il dit aussi quel conteneur le garde. Supprimez ce conteneur avant de continuer.
docker rm c41b-m-userc41b-m-userComment lire un volume sans l'attacher au service ?
Section intitulée « Comment lire un volume sans l'attacher au service ? »Pour voir ce qu'un volume contient, montez-le en lecture seule dans un
conteneur jetable. Le suffixe :ro interdit toute écriture, donc la lecture ne
modifie rien, et --rm supprime le conteneur à la fin. Le volume reste
orphelin, puisque le conteneur n'existe plus quand la commande se termine.
docker run --rm -v c41b-m-data:/d:ro "$IMAGE" ls -la /ddocker run --rm -v c41b-m-data:/d:ro "$IMAGE" cat /d/recu.txttotal 16drwxr-xr-x 3 root root 4096 Nov 4 18:32 .drwxr-xr-x 1 root root 4096 Nov 4 18:32 ..-rw-r--r-- 1 root root 12 Nov 4 18:32 recu.txtdrwxr-xr-x 2 root root 4096 Nov 4 18:32 subcommande-42Regardez la taille de recu.txt : 12 octets, soit commande-42 et son retour
à la ligne. La même lecture vérifie que la protection fonctionne : une écriture
tentée échoue avec le code 1.
docker run --rm -v c41b-m-data:/d:ro "$IMAGE" \ sh -c 'echo piege > /d/ecriture.txt'sh: can't create /d/ecriture.txt: Read-only file systemLa forme longue --mount type=volume,src=c41b-m-data,dst=/d,readonly donne le
même résultat, et la lecture marche aussi sur un volume anonyme désigné par son
nom de 64 caractères hexadécimaux. Voici le volume anonyme du début, que ANON
désigne depuis la création du conteneur : la première commande lit graine.txt,
copié depuis l'image, la seconde prouve qu'aucun conteneur ne le référence.
Relever ce nom pendant que le conteneur existait évite de chercher un volume
parmi tous les anonymes orphelins de l'hôte, dont certains ne sont pas à vous.
docker run --rm -v "$ANON":/d:ro "$IMAGE" cat /d/graine.txtdocker ps -a --filter volume="$ANON"graineCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESLa commande docker ps -a n'affiche que son en-tête : aucun conteneur ne
référence ce volume. Vous savez maintenant ce que contient chaque candidat, ce
qui évite de supprimer un volume sur sa seule mine.
Comment sauvegarder un volume avant de le supprimer ?
Section intitulée « Comment sauvegarder un volume avant de le supprimer ? »Une sauvegarde se fait avec un conteneur jetable qui monte le volume en lecture seule, et un second montage, en écriture, pour l'archive. L'archive doit vivre hors du volume que vous allez peut-être supprimer, sinon elle disparaît avec lui. Ici, un dossier de l'hôte joue ce rôle.
mkdir -p /tmp/c41b-m-bakdocker run --rm -v c41b-m-data:/source:ro -v /tmp/c41b-m-bak:/backup \ "$IMAGE" tar -czf /backup/data.tgz -C /source .ls -l /tmp/c41b-m-baktotal 4-rw-r--r-- 1 root root 184 Nov 4 18:32 data.tgzL'archive pèse 184 octets et appartient à root, puisque le conteneur écrit en
root. Une archive qui n'a pas été relue ne prouve rien. Deux relectures
complémentaires la vérifient : la liste de son contenu, qui montre que les
fichiers y sont, et le contenu d'un fichier précis, qui montre qu'il est
lisible.
docker run --rm -v /tmp/c41b-m-bak:/backup:ro "$IMAGE" tar -tzf /backup/data.tgzdocker run --rm -v /tmp/c41b-m-bak:/backup:ro "$IMAGE" \ tar -xzOf /backup/data.tgz ./recu.txt././recu.txt./sub/./sub/acommande-42Le contenu de ./recu.txt est bien commande-42. Pour détecter une altération
ultérieure, relevez l'empreinte de l'archive puis contrôlez-la avec
sha256sum -c : le contrôle répond OK tant que le fichier est intact.
cd /tmp/c41b-m-bak && sha256sum data.tgz > data.tgz.sha256 && cat data.tgz.sha256 && sha256sum -c data.tgz.sha256cd ~/donnees-orphelines6f951f3499084cd184ef95b023f5b12a1544aed2d4d52b24a0d6195f333a9577 data.tgzdata.tgz: OKUne archive tronquée se détecte aussi. Coupez une copie à 50 octets, puis
lancez la même lecture : le tar d'Alpine répond avec le code 1.
head -c 50 /tmp/c41b-m-bak/data.tgz > /tmp/c41b-m-bak/cass.tgzdocker run --rm -v /tmp/c41b-m-bak:/backup:ro "$IMAGE" tar -tzf /backup/cass.tgztar: unexpected end of filetar: short readLe message unexpected end of file signale une archive coupée : ne supprimez
jamais un volume dont la seule copie donne cette réponse. Un dernier essai
prouve que l'archive sert : extraite dans un volume neuf, elle redonne le
fichier d'origine.
docker volume create --label c41b-m-test=1 c41b-m-restoredocker run --rm -v c41b-m-restore:/d -v /tmp/c41b-m-bak:/backup:ro \ "$IMAGE" tar -xzf /backup/data.tgz -C /ddocker run --rm -v c41b-m-restore:/d:ro "$IMAGE" cat /d/recu.txtc41b-m-restorecommande-42Cette copie convient à un volume que personne n'écrit. Pour une base de données en marche, utilisez l'export logique que décrit Sauvegarder et restaurer une application.
Que devient le volume quand un projet Compose change de nom ?
Section intitulée « Que devient le volume quand un projet Compose change de nom ? »Compose nomme ses volumes projet_volume : changer le nom du projet change le
nom du volume, donc Compose en crée un nouveau, vide, et l'ancien devient
orphelin. La démonstration le reproduit avec un service Alpine qui garde un
fichier dans son volume : une vraie base PostgreSQL n'est pas nécessaire pour
voir où vont les données.
Le schéma suit le même parcours que les commandes qui viennent après. Regardez
d'abord la branche du projet c41b-m-app2, qui crée un volume vide, puis celle
du projet c41b-m-app3, qui retrouve l'ancien volume sans le recréer.
Enregistrez ce fichier sous ~/donnees-orphelines/projet/compose.yaml. Le
volume porte un label à vous, pour retrouver la démonstration au nettoyage. La
commande exec écrit un fichier dans le volume, puis down retire le
conteneur.
services: db: image: ${IMAGE} command: ["sleep","600"] volumes: - dbdata:/var/lib/datavolumes: dbdata: labels: c41b-m-test: "1"cd ~/donnees-orphelines/projetdocker compose -p c41b-m-app up -ddocker compose -p c41b-m-app exec db sh -c 'echo "ligne-ancienne" > /var/lib/data/etat.txt'docker compose -p c41b-m-app downdocker volume ls --filter name=c41b-m-app --filter dangling=true Network c41b-m-app_default Creating[...] Container c41b-m-app-db-1 Started Container c41b-m-app-db-1 Stopping[...] Container c41b-m-app-db-1 Removed Network c41b-m-app_default RemovedDRIVER VOLUME NAMElocal c41b-m-app_dbdataLe volume est resté après down, et il est orphelin. Relancer maintenant le
même fichier sous un autre nom de projet, avec l'option -p, crée un volume
qui n'a pas les données.
docker compose -p c41b-m-app2 up -ddocker compose -p c41b-m-app2 exec db cat /var/lib/data/etat.txtdocker volume ls --filter name=c41b-m-appcat: can't open '/var/lib/data/etat.txt': No such file or directoryDRIVER VOLUME NAMElocal c41b-m-app2_dbdatalocal c41b-m-app_dbdataLe fichier est introuvable dans le nouveau volume : c'est le symptôme classique
d'un projet renommé, « mes données ont disparu ». Elles n'ont pas disparu, elles
sont dans l'ancien volume. Les labels com.docker.compose.* posés par Compose
le désignent : com.docker.compose.project porte le nom de l'ancien projet,
et com.docker.compose.volume le nom du volume dans le fichier.
docker volume ls --filter dangling=true --filter label=com.docker.compose.project=c41b-m-app \ --format '{{.Name}} {{.Labels}}'docker ps -a --filter volume=c41b-m-app_dbdata --format '{{.Names}} {{.Status}}'docker run --rm -v c41b-m-app_dbdata:/d:ro "$IMAGE" cat /d/etat.txtdocker volume inspect --format '{{.Name}} {{.CreatedAt}}' c41b-m-app_dbdatac41b-m-app_dbdata c41b-m-test=1,com.docker.compose.config-hash=b84a3080856fee3da845527dc5e95d6594d6379216aca293fa56b9ad3a380d4d,com.docker.compose.project=c41b-m-app,com.docker.compose.version=5.6.1,com.docker.compose.volume=dbdataligne-anciennec41b-m-app_dbdata 2026-11-04T18:32:45ZLe filtre de label a retrouvé l'ancien volume. La deuxième commande n'a rien
affiché : aucun conteneur ne le référence. La lecture en lecture seule a
confirmé ligne-ancienne, et la dernière commande relève la date de création du
volume, à comparer plus bas. Sur un hôte réel, la sauvegarde de la section
précédente s'impose avant tout rattachement ; la démonstration s'en passe parce
que ce volume est jetable. Arrêtez ensuite le projet qui ne sert plus.
docker compose -p c41b-m-app2 downPour rattacher l'ancien volume sans le recréer, déclarez-le external, avec
son nom exact. Compose ne le crée pas et ne le gère pas : il le monte tel
quel. Le service ne doit que lire, donc le montage est en lecture seule.
Enregistrez ce fichier sous ext.yaml, dans le même dossier.
services: db: image: ${IMAGE} command: ["sleep","600"] volumes: - dbdata:/var/lib/data:rovolumes: dbdata: external: true name: c41b-m-app_dbdatadocker compose -p c41b-m-app3 -f ext.yaml up -ddocker compose -p c41b-m-app3 -f ext.yaml exec db cat /var/lib/data/etat.txtdocker compose -p c41b-m-app3 -f ext.yaml exec db sh -c 'echo x > /var/lib/data/n.txt'docker volume inspect --format '{{.Name}} {{.CreatedAt}}' c41b-m-app_dbdata Network c41b-m-app3_default Creating Network c41b-m-app3_default Creating Network c41b-m-app3_default Created Network c41b-m-app3_default Created Container c41b-m-app3-db-1 Creating Container c41b-m-app3-db-1 Created Container c41b-m-app3-db-1 Starting Container c41b-m-app3-db-1 Startedligne-anciennesh: can't create /var/lib/data/n.txt: Read-only file systemc41b-m-app_dbdata 2026-11-04T18:32:45ZRegardez trois éléments. Les données sont servies, l'écriture est refusée, et
la date de création est la même que celle relevée avant le rattachement
(2026-11-04T18:32:45Z) : le volume n'a pas été recréé. Aucune ligne
Volume ... Creating ne figure dans la sortie de up, dont certaines lignes
apparaissent deux fois quand Compose écrit hors d'un terminal interactif. Un volume external
n'est pas supprimé par down -v : arrêtez ce projet avec down -v et
vérifiez que le volume est toujours là.
docker compose -p c41b-m-app3 -f ext.yaml down -vdocker volume ls --filter name=c41b-m-app_dbdata Container c41b-m-app3-db-1 Stopping[...] Network c41b-m-app3_default RemovedDRIVER VOLUME NAMElocal c41b-m-app_dbdataPourquoi un nom de volume sans external est-il dangereux ?
Section intitulée « Pourquoi un nom de volume sans external est-il dangereux ? »Écrire seulement name: c41b-m-app_dbdata dans la section volumes, sans
external: true, semble fonctionner mais expose le volume : Compose réutilise
bien le volume existant, mais il le considère comme le sien, et un down -v du
nouveau projet le supprime. Le test suivant le démontre avec nom.yaml, une
copie de ext.yaml sans la ligne external: true. Il supprime
c41b-m-app_dbdata : sur la VM de démonstration, ce volume ne sert plus
ensuite, mais ne rejouez jamais ce test sur un volume qui porte des données
réelles.
grep -v 'external: true' ext.yaml > nom.yamldocker compose -p c41b-m-app4 -f nom.yaml up -ddocker compose -p c41b-m-app4 -f nom.yaml exec db cat /var/lib/data/etat.txtdocker compose -p c41b-m-app4 -f nom.yaml down -vdocker volume ls --filter name=c41b-m-apptime="2026-11-04T18:33:18Z" level=warning msg="volume \"c41b-m-app_dbdata\" already exists but was created for project \"c41b-m-app\" (expected \"c41b-m-app4\"). Use `external: true` to use an existing volume" Network c41b-m-app4_default Creating[...]ligne-ancienne Container c41b-m-app4-db-1 Removing Volume c41b-m-app_dbdata Removing Volume c41b-m-app_dbdata RemovedDRIVER VOLUME NAMElocal c41b-m-app2_dbdataL'avertissement du premier up nomme le problème, mais il n'arrête rien : les
données sont servies. Ensuite, down -v a supprimé c41b-m-app_dbdata, le
volume d'un autre projet, que la liste finale ne montre plus. Seul
external: true protège le volume, et c'est pourquoi la sauvegarde précède tout
rattachement. Une fois le volume supprimé, un fichier external qui le désigne ne le
recrée pas, et rejouer ext.yaml le montre.
docker compose -p c41b-m-app3 -f ext.yaml up -decho "code de sortie : $?"external volume "c41b-m-app_dbdata" not foundcode de sortie : 1C'est un garde-fou : une faute de frappe dans le nom ne produit pas un volume vide silencieux.
Pourquoi un down sans -v laisse-t-il un volume d'image orphelin ?
Section intitulée « Pourquoi un down sans -v laisse-t-il un volume d'image orphelin ? »Un docker compose down sans -v abandonne le volume anonyme issu d'un
VOLUME d'image. Ce volume n'a pas le label com.docker.compose.project :
le filtre de projet ne le retrouve pas, et aucun down -v ultérieur ne le
retirera, puisque Compose ne le rattache plus au projet. La démonstration
réutilise l'image c41b-m-img:1 construite plus haut, avec un service qui ne
déclare aucun volume. Elle enchaîne un up, un down sans -v, un second up
et un down -v.
Enregistrez ce fichier sous anon.yaml, dans le dossier du projet.
services: app: image: c41b-m-img:1cd ~/donnees-orphelines/projetdocker compose -p c41b-m-anon -f anon.yaml up -dV=$(docker inspect -f '{{range .Mounts}}{{.Name}}{{end}}' c41b-m-anon-app-1)docker compose -p c41b-m-anon -f anon.yaml downdocker volume ls --filter dangling=true --filter label=com.docker.compose.project=c41b-m-anondocker volume inspect --format '{{json .Labels}}' "$V"docker compose -p c41b-m-anon -f anon.yaml up -ddocker compose -p c41b-m-anon -f anon.yaml down -vdocker volume ls -q --filter name="$V" Network c41b-m-anon_default Creating[...] Network c41b-m-anon_default RemovedDRIVER VOLUME NAME{"com.docker.volume.anonymous":""} Network c41b-m-anon_default Creating[...] Network c41b-m-anon_default Removed4ca8a39ca46f1e2bedbf3171ec38709cc882d529d94977f478bccd9c6565c8f5La première liste par label est vide : le volume n'a aucun label de projet,
seulement {"com.docker.volume.anonymous":""}. Le down sans -v l'a donc
laissé orphelin. Le deuxième up a créé un volume différent du premier, et
down -v a bien retiré celui du conteneur courant : le volume affiché par la
dernière commande est le premier, celui que le down sans -v avait abandonné.
Un down -v ne retrouve que ce que Compose rattache au projet, et ce volume
ne l'est pas. Il n'est repérable que par dangling=true et par son contenu.
Relisez-le en lecture seule comme plus haut avant de le supprimer par son nom,
et sauvegardez-le s'il porte des données.
docker volume rm "$V"4ca8a39ca46f1e2bedbf3171ec38709cc882d529d94977f478bccd9c6565c8f5Que retire docker volume prune, avec et sans --all ?
Section intitulée « Que retire docker volume prune, avec et sans --all ? »docker volume prune supprime les volumes orphelins, mais sans --all
il ne retire que les volumes anonymes. Avec --all, il retire aussi les
volumes nommés orphelins. Un volume référencé par un conteneur, même seulement
créé, n'est jamais supprimé. L'invite par défaut le rappelle :
WARNING! This will remove anonymous local volumes not used by at least one container.
La démonstration prépare un état précis, sous un label commun c41b-m-prune,
distinct de c41b-m-test : un prune avec --all viserait sinon aussi les
volumes des sections précédentes. Trois volumes
anonymes étiquetés sont créés, celui d'un conteneur démarré, celui d'un conteneur
seulement créé, et celui d'un conteneur supprimé sans -v, qui est le seul
orphelin des trois. Côté volumes nommés : un orphelin étiqueté, un rattaché à un
conteneur créé, et un sans label.
docker run -d --name c41b-m-run \ --mount type=volume,dst=/a,volume-label=c41b-m-prune=1 "$IMAGE" sleep 600docker create --name c41b-m-stopped \ --mount type=volume,dst=/a,volume-label=c41b-m-prune=1 "$IMAGE" truedocker create --name c41b-m-gone \ --mount type=volume,dst=/a,volume-label=c41b-m-prune=1 "$IMAGE" truedocker rm c41b-m-gonedocker volume create --label c41b-m-prune=1 c41b-m-n-orphandocker volume create --label c41b-m-prune=1 c41b-m-n-useddocker volume create c41b-m-n-nolabeldocker create --name c41b-m-nuser -v c41b-m-n-used:/n "$IMAGE" truedocker volume ls --filter dangling=true --filter label=c41b-m-prune -q3ae78b972bc95ecd2281bb9d0463f6a3c82b5f9140202a65feed5a3090807f4edb0482628760f62726383aeda6acb107b03bf0cb9ae8fe6d84d537765caaaf2b1559ae4ae4a1ec0a224a00adac21f7d37506c9f9684d7b2f56e4e2d0281ff753c41b-m-gonec41b-m-n-orphanc41b-m-n-usedc41b-m-n-nolabelf27cd73187864635f0035d431728c2e5e43a596df81ef7fe397226723b8653215f55b44d6625bfa2b74c89b5a35e93e8efce8590759be3d8670b56ac8ab478bcc41b-m-n-orphanL'option volume-label de --mount pose un label sur le volume anonyme que
Docker crée : c'est le moyen de le marquer sans lui donner de nom. Les premières
lignes de la sortie sont les identifiants et les noms que les commandes de
création affichent ; les deux dernières sont la liste, qui montre ce que prune
peut atteindre : un anonyme et un nommé. Sans -f,
docker volume prune demande confirmation, et avec un stdin vide il annule
et ne supprime rien. Voici le prune sans --all :
docker volume prune -f --filter label=c41b-m-prunedocker volume ls --filter label=c41b-m-prune -qdocker volume ls -q --filter name=c41b-m-n-Deleted Volumes:5f55b44d6625bfa2b74c89b5a35e93e8efce8590759be3d8670b56ac8ab478bc
Total reclaimed space: 0B05da6f2d3ddd5b08c531e7550f0ac4bc8621870b65016758fb337c1362823109c41b-m-n-orphanc41b-m-n-usedcd23fa2890790174c466808d3df4d697ef3b07cedda6dfc4b1d3ea497ee8082dc41b-m-n-nolabelc41b-m-n-orphanc41b-m-n-usedSeul l'anonyme orphelin a disparu. Restent les deux anonymes
attachés à un conteneur, le nommé orphelin, le nommé attaché et le nommé sans
label. Le même prune avec --all retire en plus le nommé orphelin étiqueté.
docker volume prune -f --all --filter label=c41b-m-prunedocker volume ls --filter label=c41b-m-prune -qdocker volume ls -q --filter name=c41b-m-n-Deleted Volumes:c41b-m-n-orphan
Total reclaimed space: 0B05da6f2d3ddd5b08c531e7550f0ac4bc8621870b65016758fb337c1362823109c41b-m-n-usedcd23fa2890790174c466808d3df4d697ef3b07cedda6dfc4b1d3ea497ee8082dc41b-m-n-nolabelc41b-m-n-usedLe nommé attaché à un conteneur jamais démarré, et le nommé sans label, sont
restés : le label du filtre protège le second, et la référence du conteneur
protège le premier. --all est donc le geste qui supprime des données
nommées : à n'utiliser qu'avec un filtre qui désigne seulement le jetable.
Le prune refuse aussi le filtre dont vous auriez besoin pour viser les
orphelins : dangling n'est pas un filtre valide pour prune.
docker volume prune -f --all --filter label=c41b-m-prune --filter dangling=trueError response from daemon: invalid filter 'dangling'Un volume anonyme issu d'un VOLUME d'image n'a aucun label utilisable : un
prune sans filtre toucherait tous les volumes anonymes orphelins de l'hôte, y
compris ceux qui ne sont pas à vous. Supprimez-le par son nom, comme tout volume
dont vous doutez.
Comment retirer seulement ce qui est jetable ?
Section intitulée « Comment retirer seulement ce qui est jetable ? »Supprimez par nom exact, après avoir contrôlé les trois informations qui décident : les labels, le conteneur qui le référence, et le contenu. Chaque vérification écarte un cas dangereux : un label qui ne correspond pas au projet, un conteneur arrêté qui garde le volume, un contenu que personne n'a sauvegardé.
docker volume inspect --format '{{json .Labels}}' c41b-m-jetabledocker ps -a --filter volume=c41b-m-jetable --format '{{.Names}} {{.Status}}'docker run --rm -v c41b-m-jetable:/d:ro "$IMAGE" ls -la /ddocker volume rm c41b-m-jetable{"c41b-m-role":"jetable","c41b-m-test":"1"}total 8drwxr-xr-x 2 root root 4096 Nov 4 18:32 .drwxr-xr-x 1 root root 4096 Nov 4 18:33 ..c41b-m-jetableLes quatre commandes ont répondu dans l'ordre : le label, un conteneur absent (la sortie est vide), le contenu vide du dossier, puis le nom du volume supprimé.
Si le volume est encore référencé, docker volume rm répond volume is in use
et s'arrête : ne forcez pas, supprimez d'abord le conteneur qui le garde, après
avoir vérifié qu'il est lui aussi jetable. Pour que le prochain tri soit
possible, posez vos propres labels à la création : --label pour
docker volume create, et labels: sous le volume dans compose.yaml. Le
volume c41b-m-data de cette leçon portait c41b-m-role=donnees, et c'est ce
label qui l'a distingué de c41b-m-jetable d'un coup d'œil.
Comment nettoyer la démonstration ?
Section intitulée « Comment nettoyer la démonstration ? »Supprimez d'abord les conteneurs, puis les volumes, l'image et les dossiers
créés pour la leçon. Chaque commande vise le préfixe c41b-m-, jamais une
catégorie entière : vos autres ressources restent en place. Le nettoyage
supprime les volumes de la démonstration par leurs labels et leurs noms, et le
volume anonyme de c41b-m-v1 par son nom exact.
cd ~docker ps -aq --filter name=c41b-m- | xargs -r docker rm -fvdocker volume rm "$ANON"docker volume ls -q --filter label=c41b-m-test | xargs -r docker volume rmdocker volume ls -q --filter label=c41b-m-prune | xargs -r docker volume rmdocker volume ls -q --filter name=c41b-m- | xargs -r docker volume rmdocker volume ls -q --filter label=com.docker.compose.project=c41b-m-app | xargs -r docker volume rmdocker image ls -q --filter reference='c41b-m-*' | xargs -r docker image rmrm -rf /tmp/c41b-m-bak ~/donnees-orphelinesdocker volume lsDRIVER VOLUME NAMELa dernière commande doit rendre la liste de départ. Le volume anonyme de
c41b-m-v1 n'a aucun label : le nettoyage l'a supprimé à part, par le nom que
ANON a gardé depuis le début. L'image Alpine tirée pour la leçon reste en
place.
Mettre en pratique
Section intitulée « Mettre en pratique »Le lab fait travailler le même enchaînement sur un projet Compose dont le
service a perdu son volume. Deux volumes sont orphelins, l'un porte des données
à garder, l'autre est jetable. Vous reconnectez le volume à garder au service,
en lecture seule, sans le recréer, puis vous supprimez uniquement le volume
jetable, après avoir lu ses labels. L'énoncé interdit docker volume prune,
docker system prune et la suppression d'un volume sans label ou sans rapport
avec le lab. Ses tests vérifient qu'un service tourne avec le volume d'origine
monté en lecture seule, que ses labels de propriété sont intacts, que sa date de
création n'a pas changé, que les données servies sont identiques à l'attendu et
que le volume jetable a disparu. Les noms, les chemins et les valeurs
diffèrent de ceux de la démonstration.
À retenir
Section intitulée « À retenir »Un volume orphelin se juge sur son contenu, pas sur son statut.
- Un volume est orphelin quand aucun conteneur, même arrêté ou seulement
créé, ne le référence :
dangling=truene dit rien de la valeur de ses données. docker rmlaisse le volume anonyme du conteneur ;docker rm -vetdocker run --rmle retirent avec lui.- Vous retrouvez un volume par ses labels, par
--filter name=(sous-chaîne) ou pardocker ps -a --filter volume=, puis vous lisez son contenu par un conteneur jetable monté en:ro. - Vous sauvegardez avec
tarhors du volume, puis vous relisez l'archive avectar -tzfetsha256sum -c:unexpected end of filesignale une archive tronquée. - Un projet Compose renommé crée un volume vide ; l'ancien se retrouve par
com.docker.compose.projectet se rattache avecexternal: true, jamais avecname:seul, dontdown -vsupprime le volume. - Un
docker compose downsans-vabandonne le volume anonyme d'unVOLUMEd'image : il n'a pas de label de projet, et aucundown -vultérieur ne le retrouve. Supprimez-le par son nom. docker volume prunesans--allretire les anonymes orphelins, avec--allles nommés orphelins aussi ; un filtrelabelborne l'effet, et le filtredanglingest refusé.- Vous supprimez par nom exact, après avoir lu labels, conteneur et contenu.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que vous savez prévoir ce qu'une suppression laisse ou retire, et que vous retrouvez le bon volume avant d'agir.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Score par domaine
Un domaine regroupe plusieurs guides et reçoit plusieurs questions : son score est plus fiable qu'un score par thème, qui porte souvent sur une seule question.
Bilan
Points forts
Aucun sujet réussi à 80 % sur au moins deux questions pour l’instant.
Points faibles
Aucun sujet sous le seuil de réussite.
À faire ensuite
Des indices pour retenter votre chance ?
Continuer le cours : Épreuve : durcir sans casser
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications