Skip to content

Docker Volumes Explained: Named, Bind, and tmpfs Storage

Core Concept LearningJuly 6, 20265 min readUpdated July 21, 2026

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. Docker vs Kubernetes explains how that container boundary changes once an orchestrator owns replacements.

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. For the next operational layer, trace how Kubernetes reaches a workload in the Kubernetes request-flow guide.

Volumes store data outside the container filesystem
Volumes store data outside the container filesystem

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.

Without a volume, deleting the container deletes the data
Without a volume, deleting the container deletes the data

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 one a name (postgres_data), and Docker stores it outside the container's writable layer. Mount it at PostgreSQL's data path, and the database files persist when that container is replaced.

Named volumes are a portable default when Docker should manage the host location. They appear in docker volume ls, but they are not a backup: copy or snapshot the data separately and test a restore. The image process still needs permission to write the mounted path.

Named volume: Docker-managed storage for databases and production data
Named volume: Docker-managed storage for databases and production data

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.
Create data and remove the container
1docker volume create postgres_data2docker run --name pg -d \3  -e POSTGRES_PASSWORD=dev-only \4  -v postgres_data:/var/lib/postgresql/data \5  postgres:176docker exec pg psql -U postgres -c \7  "create table checks(id int primary key); insert into checks values (1);"8docker rm -f pg
Recover by mounting the same volume
1docker run --name pg-recovered -d \2  -e POSTGRES_PASSWORD=dev-only \3  -v postgres_data:/var/lib/postgresql/data \4  postgres:175docker exec pg-recovered psql -U postgres -c \6  "select * from checks;"7# Expected row: 1

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 is memory-backed and disappears when the container stops. Use it for temporary files or scratch data that should not persist in the container layer. It reduces ordinary disk persistence, but host swap and runtime security still matter; do not treat tmpfs as a complete secrets-management system.

Three Docker storage types: named volume, bind mount, tmpfs
Three Docker storage types: named volume, bind mount, tmpfs

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: useful for temporary sensitive data, but use Docker/Compose secrets or an external secret manager for delivery and access control.
  • Named volume > bind mount for production database data.
Bind mount — development workflow
1# Live-reload your app code during development2docker run -v $(pwd)/src:/app/src -p 3000:3000 myapp
tmpfs — non-persistent scratch space
1# Keep transient runtime files off the container layer2docker run --tmpfs /run/secrets:rw,noexec,nosuid myapp

Remember this

Bind mounts aid development; tmpfs is ephemeral scratch space; secret management still needs a dedicated mechanism.

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.

Zoom into one bind mount failing because host ownership differs
Zoom into one bind mount failing because host ownership differs

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.

Sharing Volumes Between Containers

Multiple containers can mount the same volume simultaneously. An app container might write data to shared_data while a backup container mounts it read-only and copies a consistent snapshot.

Docker exposes the shared filesystem but does not coordinate application-level concurrency, locking, or crash consistency. The applications and storage driver must support the access pattern. Do not run multiple independent database instances against one data directory unless that database explicitly supports it.

Multiple containers can mount the same volume
Multiple containers can mount the same volume

Quick reference

  • Same volume name in -v flag on multiple containers.
  • App + backup sidecar is a common pattern.
  • Compose: define volume once, reference in multiple services.
  • Read-only share: mount :ro on the backup container.
  • One writer per database volume — no concurrent DB containers.
  • docker run --volumes-from copies mounts from another container.

Remember this

One volume, many containers — great for backups and sidecars, but coordinate write access.

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.

Key takeaway

Use named volumes when data must outlive a container, bind mounts when a host path is intentionally part of the development workflow, and tmpfs for non-persistent scratch data. Persistence is not backup: protect important volume data with a separate, tested restore process.

Practice (25 min): Run the PostgreSQL workflow above, insert a row, remove the container, and mount postgres_data into a replacement; the row should still be present. Intentionally run docker volume rm postgres_data while it is attached and use the error to identify the owning container. Recover by preserving the named data volume, removing only the disposable container, and deleting a separate scratch volume. Pass when the replacement returns the row and docker volume ls proves only the intended scratch volume was deleted.

Share:

Related Articles

Docker and Kubernetes are not competitors on the same layer, and treating them as an either/or is the mistake that leads

Read

Containers are the foundation of modern cloud deployment, but default container images often ship with bloated Linux OS

Read

A team notices their production image is 1.4GB for an app whose actual runtime code is a few megabytes — the rest is a f

Read

Explore this topic

Keep learning

Follow a structured path or browse all courses to go deeper.