Topic 3.2
Named Volumes
In one line
The recommended, Docker-managed way to persist data — Docker decides where it physically lives, and you refer to it by a simple name.
Key ideas
- 01
A NAMED VOLUME is storage that Docker creates and manages for you, identified by a name you choose (e.g.
pgdata) — you don't need to know or care exactly where on the host filesystem it physically lives; Docker handles that. - 02
Create one explicitly with
docker volume create pgdata, or let Docker create it automatically the first time you reference a new volume name in adocker run -vordocker-compose.yml— both approaches end up identical. - 03
Attach a named volume with
-v volumename:/path/inside/container— Docker mounts that volume's storage at the given path INSIDE the container, so anything the app writes to that path is actually being written into the persistent volume, not into the container's disposable writable layer. - 04
The critical insight: the PATH you mount to matters enormously — you must mount the volume at the exact directory the application actually writes its persistent data to (for Postgres, that's
/var/lib/postgresql/data; check any official image's documentation for the correct path for that specific app). - 05
Reattaching the SAME named volume to a brand-new container instantly gives that new container access to all the old data — this is exactly how you upgrade a database's container/image version without losing any data: stop the old container, start a new one (new image version) with the SAME volume name attached.
- 06
docker volume lslists all volumes on your system.docker volume inspect <name>shows details including its actual physical Mountpoint on the host (useful for debugging, rarely needed day to day).docker volume rm <name>permanently deletes a volume and all its data — there's no undo, so be as careful with this as you would be withrm -rfon real files. - 07
A volume can be shared between MULTIPLE containers simultaneously (mounted into more than one at once) — useful for sharing data between cooperating containers, though this needs care around concurrent writes from multiple processes.
In your stack
- →
The corrected, persistent version of the previous topic's Postgres example:
docker run -d --name pg -e POSTGRES_PASSWORD=secret -v pgdata:/var/lib/postgresql/data postgres:16— now removing and recreating this container, as long as you reattach the SAMEpgdatavolume, preserves every row.
Code & diagrams
The exact fix for last topic's data-loss problem.
# Create a named volume explicitly (optional — Docker will auto-create it if you skip this)
docker volume create pgdata
# Run Postgres WITH the volume mounted at its actual data directory
docker run -d --name pg -e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
# Insert data
docker exec -it pg psql -U postgres -c "CREATE TABLE test (id int); INSERT INTO test VALUES (1);"
# Remove the container entirely — but the VOLUME survives independently
docker rm -f pg
# Start a brand-new container, reattaching the SAME volume
docker run -d --name pg -e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
# The data is STILL THERE, because it never lived in the container to begin with
docker exec -it pg psql -U postgres -c "SELECT * FROM test;"
# id
# ----
# 1
# Inspect the volume, list all volumes, and (carefully) remove one
docker volume inspect pgdata
docker volume ls
docker volume rm pgdata # irreversible — deletes the data for realExplain it without notes
Why does mounting a volume at the WRONG path (e.g. /data instead of Postgres's actual /var/lib/postgresql/data) fail to fix the data-loss problem, even though a volume is technically attached?
You want to upgrade Postgres from version 15 to 16 without losing data. Describe the exact sequence of Docker commands.
Practice
Recreate this topic's full named-volume exercise yourself and confirm the data survives container recreation.
Run docker volume inspect on a volume you created and find its real Mountpoint path on your host filesystem — if you have host access, look at what's actually stored there.
Trade-offs
- ↔
Named volumes trade a small amount of 'where exactly is my data' transparency (Docker abstracts the physical location) for a much simpler, more portable mental model — you refer to volumes by name across any machine that has Docker, without caring about host-specific file paths, which is exactly what the next topic's alternative (bind mounts) does NOT give you.
Done when you can
I can attach a named volume to a container at the correct path for a given application.
I've personally upgraded a containerized database's version while preserving data via a shared volume.
I understand that mounting at the wrong path silently fails to persist anything useful.