Walk through the lifecycle of a Docker named volume: how you create one, how you find out where its data physically lives, how it gets attached to a container, and what happens to the data when that container is deleted.
answer
- create / ls / inspect / rm — four verbs
- Mountpoint = /var/lib/docker/volumes/<name>/_data
- named survives docker rm; anonymous dies with -v
- "volume is in use" → a stopped container still holds it
- docker system df -v for size
basics
~20 sCreate with docker volume create name, list with docker volume ls, see its host path and driver with docker volume inspect name, attach with -v name:/path. Named volumes outlive containers: deleting the container leaves the volume until you run docker volume rm.
solid answer
~50 sA named volume is a storage object managed by the Docker daemon, independent of any container. `docker volume create app-data` creates it; `docker volume ls` lists volumes; `docker volume inspect app-data` shows its driver, options, labels and `Mountpoint` (for the built-in `local` driver, typically `/var/lib/docker/volumes/app-data/_data`). You attach it at run time with `-v app-data:/var/lib/postgresql/data` or the more explicit `--mount type=volume,src=app-data,dst=/var/lib/postgresql/data`; if it does not exist, Docker creates it implicitly. Lifecycle is the key point: the volume is **not** owned by the container. `docker rm` (even `docker rm -v`) does not delete a named volume — only anonymous ones. The data survives container removal, image upgrades and daemon restarts, which is exactly why databases use volumes. You delete it explicitly with `docker volume rm app-data`, and Docker refuses while any container (even a stopped one) still references it.
code
bash · 11 linesdocker volume create app-data
docker volume inspect app-data --format '{{.Driver}} {{.Mountpoint}}'
docker run -d --name db \
--mount type=volume,src=app-data,dst=/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=secret postgres:16
docker rm -f db # volume and data still there
docker volume ls | grep app-data
docker volume rm app-data # explicit deletego deeper
Know the four commands (create, ls, inspect, rm) and the headline rule: named volumes outlive containers and must be deleted explicitly.
Add the distinctions — named vs anonymous under docker rm -v and --rm, -v vs --mount syntax, why volume is in use appears, and what inspect fields mean.
Frame it operationally: volumes are the state boundary in a redeploy, disk creep is the real failure mode, docker system df -v and label conventions are how you keep a host inventory manageable.
Talk policy — naming and labelling conventions so every volume traces to an owning service, who is allowed to delete state, and the fact that host-local volumes tie a stateful workload to one machine, which constrains your placement and DR story.
## What a named volume actually is A container's writable layer is throwaway: it is created with the container and destroyed with it. A **volume** is a separate, daemon-managed storage object with its own name and its own lifetime. Containers reference volumes; they do not own them. That single sentence explains almost every behaviour below. ## Creating ``` docker volume create app-data ``` This registers a volume with the default driver (`local`) and no options. You rarely have to run it explicitly: if you start a container with `-v app-data:/data` and no such volume exists, the daemon creates it on the spot with default settings. Explicit creation matters when you want to set something at creation time — labels (`--label app=billing`) or driver options — because those cannot be changed later; you would have to remove and recreate the volume. ## Listing and inspecting ``` docker volume ls docker volume ls -f dangling=true # volumes no container references docker volume inspect app-data ``` `inspect` returns JSON with the fields that matter operationally: - `Driver` — which storage plugin manages it (`local` unless you chose otherwise). - `Options` — the driver options captured at creation. - `Mountpoint` — where the data sits for the `local` driver on Linux: `/var/lib/docker/volumes/app-data/_data`. - `Scope` — `local` (this host) or `global` (a cluster-wide plugin). - `Labels`, `CreatedAt`. Treat `Mountpoint` as *diagnostic*, not as an interface. It is a real host path on Linux and you can read it as root, but on Docker Desktop for macOS/Windows the daemon runs inside a Linux VM, so that path does not exist on your laptop. Tooling that pokes at `/var/lib/docker/volumes` directly breaks the moment the driver changes, so it is not the supported way to move data in and out. ## Attaching to a container Two syntaxes, same underlying object: ``` docker run -d -v app-data:/var/lib/postgresql/data postgres:16 docker run -d --mount type=volume,src=app-data,dst=/var/lib/postgresql/data postgres:16 ``` The short `-v` form is terse and ambiguous (the first field is a volume name if it has no slash, a host path if it does). `--mount` is explicit key/value, fails loudly on typos, and is the only way to pass some options (such as `volume-nocopy` or `readonly` in a self-documenting way). Prefer `--mount` in anything you commit. At container start the daemon mounts the volume's directory over the target path inside the container's mount namespace. Anything the image had at that path is hidden by the mount — though for an *empty* volume Docker first copies the image content into it ("copy-up"), which is a separate behaviour worth knowing. Many containers may mount the same volume simultaneously; Docker does no locking, so concurrent writers need an application that tolerates it (two Postgres instances on one data directory will corrupt it). ## Removal — the part interviews test - `docker stop` / `docker rm` on the container: the volume and its data **survive**. - `docker rm -v` (or `docker run --rm`): removes *anonymous* volumes attached to that container; a **named** volume is untouched. - `docker volume rm app-data`: the explicit delete. It fails with "volume is in use" if any container — including a stopped or created-but-never-started one — still references it. `docker ps -a --filter volume=app-data` finds the holder. - `docker compose down`: removes containers and networks but keeps named volumes; `docker compose down -v` removes the volumes the Compose file declares. - `docker volume prune`: bulk-removes unused volumes; on modern Engine versions that means anonymous ones only unless you pass `--all`. Because deletion is always explicit for named volumes, the usual production failure is not data loss but disk creep: volumes from long-gone containers piling up under `/var/lib/docker/volumes`. `docker system df -v` shows per-volume size and is the right first command when a host fills up. ## Why this matters Volumes are the supported way to keep state across the whole reason containers are attractive: replacing a container is routine (new image tag, new config, crash restart), and every replacement destroys the writable layer. Putting the database directory, upload directory or cache on a named volume decouples "the process I redeploy constantly" from "the bytes I must never lose".
- Why does `docker volume rm` fail for a volume whose container was stopped hours ago?A stopped container still exists as a Docker object and still holds its mount references, so the daemon refuses to delete the volume underneath it. Remove or recreate the container first (`docker rm <id>`), then delete the volume. `docker ps -a --filter volume=<name>` lists every container, running or not, that references it.
- Can you rename or resize a named volume in place?No. There is no `docker volume rename`, and driver options such as size or NFS parameters are fixed at creation. The supported path is to create a new volume with the settings you want and copy the data across with a helper container that mounts both, then repoint the workload and delete the old volume.
- Is reading `/var/lib/docker/volumes/<name>/_data` from the host a legitimate way to work with volume data?It is fine for a quick look on a Linux host as root, but it is not a supported interface. The path only exists for the built-in `local` driver, it does not exist at all on Docker Desktop where the daemon runs inside a VM, and writing there bypasses the daemon's bookkeeping. Use a helper container that mounts the volume instead.
A container is a rented apartment; a named volume is the storage unit down the street. Moving out of the apartment (removing the container) does not empty the storage unit — you have to go cancel that contract yourself.
saying these in an interview costs you the question
- Saying that removing the container removes its named volume — data loss is the opposite of what happens.
- Believing `docker run --rm` cleans up named volumes; it only removes anonymous ones.
- Treating `/var/lib/docker/volumes/...` as the API and building backup scripts around it.
- Thinking a volume must be created before use — Docker auto-creates it on first reference, which is exactly how stray volumes appear.
- Assuming `docker compose down` wipes the database volume, or that it never does (it does with `-v`).