Docker can attach storage to a container as a bind mount, a named volume, or a tmpfs mount. How do these three differ, and when would you reach for each?
answer
- bind = host path, you manage it
- volume = Docker manages, survives docker rm
- empty volume pre-populated from image; bind mount hides it
- tmpfs = RAM only, Linux, dies on stop
- all three bypass copy-on-write
basics
~20 sA bind mount maps a host path into the container — good for local source code and config. A named volume is Docker-managed storage that outlives containers — good for databases and app data. A tmpfs mount lives only in RAM — good for scratch files and secrets.
solid answer
~60 sAll three replace what the image has at a container path, but the backing store differs. - **Bind mount** (`-v /host/path:/in/container`): a specific host directory or file. You control the exact location; Docker manages nothing. Best for development source code, config files and certificates mounted read-only. It couples the container to the host layout and gives it real host filesystem access, so it is a poor fit for production data. - **Named volume** (`-v mydata:/var/lib/postgresql/data`): storage Docker creates and tracks by name, stored under Docker's data root with the built-in `local` driver. It survives `docker rm`, is portable across hosts and Compose files, can be backed by plugin drivers, and an empty one is pre-populated from the image's content at that path. This is the default choice for persistent application data. - **tmpfs** (`--tmpfs /tmp`): RAM-backed, Linux-only, never written to the container's writable layer or to disk, and destroyed when the container stops. Best for scratch space and short-lived sensitive material. All three bypass the copy-on-write layer, so writes are faster than writing into the container's own filesystem.
code
bash · 9 lines# bind mount: an exact host directory
docker run -v /home/dev/app:/app node:22 npm run dev
# named volume: Docker-managed, survives container removal
docker volume create pgdata
docker run -v pgdata:/var/lib/postgresql/data postgres:17
# tmpfs: RAM only, gone when the container stops
docker run --tmpfs /tmp:size=64m alpine shgo deeper
Be able to name all three, give one everyday use case each, and state clearly that a named volume survives container removal while tmpfs does not survive a stop.
Add the mechanics: mounts bypass the copy-on-write layer, an empty named volume is pre-populated from the image while a bind mount hides image content, and anonymous volumes are the ones that pile up.
Frame it as an operational choice — volumes for state you back up and upgrade around, bind mounts only for host-owned config and dev loops, tmpfs to keep secrets and scratch off disk — and mention the Docker Desktop performance difference.
Talk about the policy: state belongs in named volumes or external services so hosts stay disposable, bind mounts of host paths are an escape hatch that has to be justified and audited (especially the Docker socket), and standardising this is what makes workloads portable to orchestrators later.
## Why mounts exist at all A container's own filesystem is a stack of read-only image layers plus one thin writable layer on top, managed by a storage driver (overlay2 on most Linux hosts). That writable layer has two problems. First, it is tied to the container: `docker rm` destroys it, so anything written there is gone. Second, copy-on-write is slow for write-heavy workloads — modifying a large file first copies the whole file up out of the image layer. A mount solves both. When Docker starts a container it builds a private mount namespace, and for each requested mount it mounts something else over the given path. Reads and writes at that path go straight to the backing filesystem, completely bypassing the union filesystem and the container lifecycle. ## Bind mounts A bind mount attaches an existing host path — a directory or a single file — to a path inside the container. The host path is absolute and fully under your control; Docker stores no metadata about it and `docker volume ls` will never show it. Strengths: you can see and edit the files with normal host tools, which makes it the natural fit for mounting a source tree into a dev container so edits appear immediately, or for injecting `nginx.conf`, TLS certs or a `.env` file read-only. Weaknesses: it hard-codes host layout into your run command, which breaks portability across machines and CI. It is also the biggest foot-gun for security — a bind mount of `/`, `/etc` or `/var/run/docker.sock` effectively hands the host to the container. Ownership is host ownership, so the container's user id must line up with the host file owner (a topic in its own right). ## Named volumes A named volume is storage Docker creates, names and tracks. With the default `local` driver its data lives under Docker's data root (typically `/var/lib/docker/volumes/<name>/_data` on Linux), but you should treat that path as an implementation detail and go through `docker volume` commands. Properties that matter in interviews: - **Lifecycle independence.** Removing the container does not remove the volume; only `docker volume rm` or `docker volume prune` does. Data survives image upgrades — that is exactly how you upgrade a database container. - **Pre-population.** If the volume is empty the first time it is mounted, Docker copies whatever the image already has at that container path into the volume. A bind mount never does this; it simply hides the image content. - **Portability.** The run command mentions only a name, so the same Compose file works on a laptop, a CI runner and a server. - **Pluggable backing.** Driver options let a volume be backed by NFS or a plugin instead of a local directory. - **Speed on Docker Desktop.** On macOS and Windows, volumes live inside the Linux VM's own disk, while bind mounts cross a host↔VM filesystem bridge. For anything IO-heavy the volume is dramatically faster. A related form is the **anonymous volume**: same storage, no name — created by a Dockerfile `VOLUME` instruction or by `-v /path/in/container` with no source. It gets a random hex ID, is easy to lose track of, and is the usual cause of "why is my disk full of volumes". ## tmpfs mounts A tmpfs mount is a RAM-backed filesystem mounted into the container. Nothing is written to the image, the writable layer, or a host directory. When the container stops, the content is gone. Use it for scratch files, caches you never want to persist, and short-lived credentials you do not want landing on disk. It is Linux-containers-only, cannot be shared between containers, and its content counts against the container's memory — an unbounded tmpfs can get the container OOM-killed, so set a size. ## Choosing - Persistent application state (database files, uploaded content, message-broker data) → **named volume**. - Live source code during development, host config injected read-only, host log directories → **bind mount**. - `/tmp`, `/run`, scratch, in-memory secrets, and the writable holes you punch in a `--read-only` container → **tmpfs**. A useful default: if the container itself owns the data, use a volume; if the host owns the data, use a bind mount; if nobody should own it after the process exits, use tmpfs.
- Does `docker rm mycontainer` delete the data in a named volume the container used?No. Named volumes have a lifecycle independent of any container, so the data stays and can be mounted into a replacement container. That is what makes in-place image upgrades of stateful services safe. `docker rm -v` does remove *anonymous* volumes attached to that container, and `docker volume rm` or `docker volume prune` removes named ones explicitly.
- Where does a named volume actually live on a Linux host, and should you edit it there?With the default `local` driver it is a directory under Docker's data root, usually `/var/lib/docker/volumes/<name>/_data`. You can read it as root, but treat it as an implementation detail: another driver puts the data somewhere else entirely, and poking at it directly bypasses permissions and can confuse a running container. Prefer a throwaway container that mounts the volume for backup or inspection.
- Why is a bind mount of a source tree slow on Docker Desktop but fast on a Linux server?On a Linux server the container shares the host kernel and the bind mount is a native kernel bind — essentially free. On macOS and Windows the containers run inside a Linux VM, so a host bind mount has to be shared across the VM boundary over a file-sharing layer such as VirtioFS, which adds per-operation latency. Named volumes live inside the VM's disk and avoid that crossing.
A bind mount is a window cut into the host's own filing cabinet; a named volume is a storage locker the building manages and hands you by number; tmpfs is a whiteboard wiped clean when you leave the room.
saying these in an interview costs you the question
- Saying bind mounts and named volumes are "the same thing with different syntax".
- Claiming volume data is deleted when the container is removed.
- Assuming tmpfs content survives a container restart, or that it is written to disk somewhere.
- Believing you must add a `VOLUME` instruction to the Dockerfile for data to persist — that only creates an anonymous volume you did not name.
- Saying a bind mount over a non-empty image directory merges the two sets of files, rather than hiding the image content.