Search across all documentation pages
--mount vs -v, UID/GID mapping, read-only mounts.Create a named volume and mount it into a container.
docker volume create pgdata
docker run -d --name db -v pgdata:/var/lib/postgresql/data postgres:16The database writes to /var/lib/postgresql/data, but the bytes live in pgdata and survive docker rm db.
For live-editing source during development, bind mount a host directory instead.
docker run --rm -v "$PWD/src:/app/src" node:22 node /app/src/index.jsA Compose stack usually mixes a named volume for data with a read-only bind mount for config.
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
cache:
image: redis:7
tmpfs:
- /data
volumes:
pgdata:The pgdata named volume holds durable database files.
The init.sql bind mount is read-only (:ro) so the container cannot alter your host file.
The Redis tmpfs keeps its scratch data in RAM, which never touches disk.
docker compose up -d
docker volume inspect myproject_pgdataA named volume is created and stored by the engine under its own data root, and Docker tracks its lifecycle.
Because the engine owns it, a fresh empty volume is initialized with the contents of the container path on first mount, and it is portable across hosts via backup or volume plugins.
A bind mount points at an exact host path you choose, and it shadows whatever was at that path in the image.
There is no lifecycle tracking - delete the host directory and the data is gone.
--mount syntaxThe older -v shorthand is terse but ambiguous; --mount is explicit and preferred for anything non-trivial.
docker run -d \
--mount type=volume,source=pgdata,target=/var/lib/postgresql/data \
--mount type=bind,source="$PWD/conf",target=/etc/app,readonly \
postgres:16A key difference: with -v, a bind source that does not exist is created as an empty directory; with --mount, a missing bind source errors out, which catches typos.
Files in a volume or bind mount keep their numeric UID and GID, not usernames.
If your image runs as UID 1000 but the host directory is owned by UID 0, writes fail with permission errors.
docker run --rm -v "$PWD/data:/data" --user 1000:1000 alpine:3.20 \
sh -c 'touch /data/ok || echo "permission denied"'The fix is to align the container user with the directory owner, which the next page covers in depth.
A tmpfs mount lives in host memory and is never written to disk.
It is ideal for sensitive scratch data - decrypted secrets, session files - because it vanishes when the container stops and leaves no on-disk trace.
Mounting over a non-empty image directory hides the image's files for the life of the mount; a bind mount of an empty host dir onto /app makes the app "disappear".
Named volumes initialize from the image path only when empty - if the volume already has data, the image's default contents are ignored.
Anonymous volumes (-v /data with no name) accumulate as untagged clutter; prune them with docker volume prune and prefer named volumes.
Bind mounts on Docker Desktop cross a virtualization boundary, so heavy I/O (node_modules, database files) is far slower than a named volume - keep those in volumes.
Removing a container does not remove its named volumes; use docker rm -v or docker compose down -v when you truly want the data gone.
Named volume: the default for persistent app and database state; portable and engine-managed.
Bind mount: best for development source code and injecting config files from the host.
tmpfs mount: for secrets and scratch that must never hit disk.
Volume plugins / CSI: for networked or cloud storage; in Kubernetes this becomes a PersistentVolumeClaim bound by a CSI driver, the correct multi-node choice.
Will my data survive docker rm?
Yes, if it is in a named volume or bind mount. Data in the container's writable layer is deleted.
Should I use -v or --mount?
Prefer --mount for clarity and because it errors on missing bind sources instead of silently creating them.
Why did my app files disappear after mounting? A mount shadows the image contents at that path. Mount to a different path or seed the volume first.
How do I make a mount read-only?
Append :ro with -v, or add readonly with --mount.
Do volumes work across a Kubernetes cluster? Plain Docker volumes are single-host. Use a CSI-backed PersistentVolumeClaim in Kubernetes.
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026