Docker Volumes Explained: Named, Bind, and tmpfs Storage
Containers are ephemeral by design — when you remove one, its filesystem disappears with it. That is fine for stateless apps, but databases, uploaded files, and logs need to survive restarts and redeploys. Docker volumes solve this by storing data outside the container layer.
This guide explains why volumes matter, the three storage types (named volumes, bind mounts, tmpfs), how to share data between containers, and the commands you use daily. If you have ever lost database data after `docker rm`, this is the fix.
Why Docker Volumes?
A container filesystem is a thin writable layer on top of an image. Anything written inside the container lives in that layer. When the container is deleted, the layer is deleted too — along with your database files, uploads, and logs.
A volume stores data on the host (or in Docker's managed storage area) and mounts it into the container at a path like `/var/lib/mysql`. The container can read and write the volume, but the data belongs to the volume — not the container. Delete the container, start a new one, mount the same volume, and your data is still there.
Quick reference
- Without volume: container deleted → data deleted.
- With volume: container deleted → data remains safe.
- Volumes survive container restarts, upgrades, and replacements.
- Images are immutable; volumes hold mutable runtime state.
- Use volumes for databases, file uploads, and application logs.
- Container storage is for temporary cache and build artifacts only.
Remember this
Volumes decouple data lifetime from container lifetime — essential for anything that must persist.
Named Volumes
Named volumes are created and managed by Docker. You give them a name (`mysql_data`), and Docker stores the data in a directory on the host that you do not need to manage manually. Mount a named volume into a MySQL container at `/var/lib/mysql`, and database files persist across container replacements.
Named volumes are the default choice for production databases and any data you want Docker to manage cleanly. They work across platforms, back up easily with `docker run --volumes-from`, and appear in `docker volume ls`. Docker handles permissions and storage location.
Quick reference
- Created with: docker volume create mysql_data
- Mounted with: -v mysql_data:/var/lib/mysql
- Managed by Docker — no host path required.
- Best for: PostgreSQL, MySQL, Redis persistence, uploads.
- Survives docker rm on the container.
- Reusable: new container mounts same volume by name.
Remember this
Named volumes are Docker-managed persistent storage — the production default for databases.
Bind Mounts and tmpfs
Not every mount is a named volume. A bind mount maps a specific host directory into the container — for example `-v ./src:/app/src`. Edit files on your laptop and see changes instantly inside the container. Bind mounts are ideal for local development where you want live code reload without rebuilding the image.
A tmpfs mount stores data in memory (RAM), not on disk. It disappears when the container stops. Use tmpfs for temporary files, sensitive secrets you do not want written to disk, or high-speed scratch space. tmpfs mounts are fast but not persistent.
Quick reference
- Bind mount: host path → container path (-v /host:/container).
- Bind mount: host changes appear inside container immediately.
- Bind mount: risky in production — host path coupling.
- tmpfs: data lives in RAM — gone when container stops.
- tmpfs: good for secrets, temp files, sensitive caches.
- Named volume > bind mount for production database data.
Remember this
Bind mounts for dev convenience; tmpfs for ephemeral secrets; named volumes for production persistence.
Bind Mounts in Practice
Bind mounts create a direct bridge between a host folder and a container path. Your project directory on disk becomes `/app` inside the container. Tools like Docker Compose use bind mounts heavily in development: mount source code, run the app in a container, edit files in your IDE, and the running process picks up changes.
The trade-off is coupling. The container now depends on a specific host path existing. That path differs between developers' machines and does not exist in CI or production the same way. Never bind-mount production database directories — use named volumes instead.
Quick reference
- Syntax: -v /absolute/host/path:/container/path
- Relative paths work: -v ./data:/app/data
- Read-only bind: append :ro to the mount.
- Compose: volumes: - ./src:/app/src in service definition.
- Watch out for file permission mismatches (UID/GID).
- Production: prefer named volumes over bind mounts.
Remember this
Bind mounts trade portability for dev speed — perfect locally, avoid in production.
Essential Volume Commands
Docker provides a small CLI for volume management. List all volumes with `docker volume ls`. Create one explicitly with `docker volume create mydata` before running a container, or let Docker auto-create it on first mount. Inspect a volume to see its mount point on the host with `docker volume inspect mydata`.
Remove a single volume with `docker volume rm mydata` — only when no container is using it. Clean up all unused volumes at once with `docker volume prune` (careful: this deletes data). Remember: deleting a container does not delete its volumes unless you pass `--volumes` to `docker rm` or `docker compose down -v`.
Quick reference
- docker volume ls — list all volumes.
- docker volume create mydata — create named volume.
- docker volume inspect mydata — show mount point and driver.
- docker volume rm mydata — delete one volume.
- docker volume prune — remove all unused volumes.
- docker rm -v — remove container AND its anonymous volumes.
- docker compose down -v — remove compose volumes too.
Remember this
Delete container ≠ delete volume — use docker volume rm or prune explicitly.
Docker volumes are how you add persistence to ephemeral containers. Use named volumes for databases and production data, bind mounts for local development with live reload, and tmpfs for secrets and temporary files that should never touch disk. Mount volumes at the right path, share them between containers when needed, and remember that removing a container leaves the volume intact — which is usually exactly what you want.
Related Articles
Explore this topic