Docker Volumes#
Docker provides three mechanisms for persisting or sharing data between a container and the outside world :
| Mechanism | Flag | Data lifecycle |
|---|---|---|
| Bind mount (filesystem mapping) | -v /host/path:/container/path | Lives on the host |
| Named / anonymous volume | -v name:/container/path or VOLUME | Managed by Docker, survives container removal |
| tmpfs | --tmpfs /path | In RAM; lost on container stop |
This article focuses on the volume mechanism and the VOLUME Dockerfile instruction.
The VOLUME Instruction#
VOLUME ["/path"] declares a mount point inside an image and marks it as externally managed . At container start, Docker automatically creates an anonymous volume and mounts it at the declared path unless an explicit -v is provided at docker run time.
Two syntax forms are accepted:
VOLUME ["/data"] # JSON array form (preferred)
VOLUME /data # shell form
The host directory cannot be specified inside a Dockerfile — it is resolved at container run-time to preserve image portability .
See the anonymous-volume example Dockerfile for the minimal pattern (note: RUN after VOLUME here writes to the working directory, not to /data, so the divergence described below does not apply).
VOLUME + RUN Ordering: The Critical Divergence#
The placement of VOLUME relative to RUN instructions is a common source of confusion, and the two Docker build backends behave differently :
Legacy builder: any changes made to the declared volume directory by subsequent
RUNinstructions are discarded.
BuildKit: changes made afterVOLUMEare retained in the image layer.
The course's TP10 Dockerfile illustrates this exact scenario :
- Files are added to
/mon-dossierbeforeVOLUME—fichier1.txt,fichier2.txt VOLUME ["/mon-dossier"]is declared- A third file is added after
VOLUME—fichier3.txt
When you run a container from this image with BuildKit (the default since Docker 23.0), all three files are visible :
fichier1.txt fichier2.txt fichier3.txt
With the legacy builder, fichier3.txt would be missing because the post-VOLUME RUN write is silently dropped.
Practical rule: place all
RUNinstructions that seed volume content before theVOLUMEdeclaration to behave consistently across both builders.
Anonymous vs. Named Volumes#
Anonymous volumes are created automatically when VOLUME is used in a Dockerfile or when -v /container/path (no name) is passed to docker run. They have a random ID and are not easily reused across containers .
Named volumes are created explicitly and can be shared between containers :
docker volume create my-data
docker run -v my-data:/data busybox
Key volume management commands:
docker volume ls
docker volume inspect my-data
docker volume rm my-data
Course Exercises (TP8–TP10)#
| TP | Topic | Reference |
|---|---|---|
| TP8 | Serve static files via Nginx using a bind mount or named volume | |
| TP9 | Share data between two containers via a named volume | |
| TP10 | Observe VOLUME + RUN interaction; BuildKit vs. legacy behavior |
Primary Sources#
- Course chapter —
content/chapitres/volumes.adoc— full slides and exercise solutions - TP10 Dockerfile —
content/code-samples/volumes/tp10/Dockerfile— the canonicalVOLUME/RUNordering example - Anonymous volume Dockerfile —
content/code-samples/volumes/anonymes/Dockerfile - Docker official reference —
VOLUMEinstruction docs