Docker
Intermediate 14 min read Docker

Docker Volumes & Data Persistence

Containers are ephemeral — their writable layer dies with them. Volumes, bind mounts and tmpfs mounts are the three ways to persist or share data safely.

volumesbind mountstmpfsnamed volumespersistencedocker compose
Introduction

What is this?

Docker offers three storage options: named volumes (managed by Docker in its storage area), bind mounts (any host directory mapped into the container), and tmpfs (in-memory only). Named volumes are the recommended default for persistent data.

Motivation

Why do you need it?

  • Databases and application state must survive container recreation.
  • Volumes are portable with the container and shareable between containers.
  • tmpfs gives you fast in-memory storage that never touches disk.
  • Persisting data to the host makes debugging easy: inspect files directly.
Think about it

Mental model

Imagine

A USB drive you plug into a computer

Think of

A Docker volume

The drive keeps your files even when the computer reboots, and you can move it between computers — exactly how a volume outlives containers and can be shared.

Mechanics

How it works

  • Named volumes live under /var/lib/docker/volumes on the host, managed by Docker.
  • A volume is mounted at a container path; writes go to the volume, not the container's writable layer.
  • Bind mounts map any host path directly (./data:/app/data) and reflect changes instantly.
  • tmpfs mounts exist only in memory and are destroyed when the container stops.
  • Backing up a named volume means exporting its mount point contents (or using docker run --volumes-from with a tar).

Three storage types and where data lives.

Named volume
Bind mount
tmpfs
Container mount point
Reference

Key commands

docker volume create mydata

Create a named volume explicitly.

docker run -v mydata:/app/data app

Mount a named volume at /app/data.

docker run -v $(pwd)/config:/etc/app/config app

Bind-mount a host directory (absolute path required).

docker volume ls

List volumes.

docker run --tmpfs /cache app

Mount an in-memory tmpfs at /cache.

Hands-on

Examples

Persist a database with a named volume

Persist a database with a named volume
docker volume create pgdata
docker run -d --name postgres \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
# Stop, remove, and recreate the container — data survives:
docker rm -f postgres
docker run -d --name postgres \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16

The named volume pgdata stores PostgreSQL's data directory. Even after the container is deleted, the volume remains and the new container mounts the same data.

Real world

In production

  • Database engines persist via named volumes (Postgres, MySQL, Redis).
  • Bind mounts are used in development for hot reload; rarely in production.
  • Shared config/secrets via read-only bind mounts from the host.
  • tmpfs for ephemeral caches or tmpdirs that should never persist.
Guidelines

Best practices

  • Prefer named volumes over bind mounts — Docker manages pathing and permissions.
  • Mount config as read-only (:ro) to prevent accidental modification.
  • Back up volumes regularly (dump the DB, not the volume directory blindly).
  • Don't mount the Docker socket into containers unless absolutely necessary.
Watch out

Common mistakes

  • Storing data in the container's writable layer — it's lost on docker rm.
  • Using relative paths in bind mounts (must be absolute or $PWD).
  • Assuming volumes are deleted with docker rm — they are not; use docker volume rm.
  • Mounting volumes with permission mismatches (UID/GID issues).
Root cause analysis

Common issues

Error
Permission denied when writing to a volume
Root cause

Container process UID doesn't match host directory ownership.

Fix

Run the container with a matching UID (docker run --user $(id -u):$(id -g)), or chown the host dir.

Error
Data missing after container recreation
Root cause

Volume wasn't mounted, or data went to the writable layer.

Fix

Verify with docker inspect that the mount path matches the app's data dir.

Error
docker volume rm: volume is in use
Root cause

A container (even stopped) references it.

Fix

Remove referencing containers first, then the volume.

When things break

Debugging tips

  • docker volume ls and docker volume inspect to find and inspect volumes.
  • docker inspect -f '{{ json .Mounts }}' ID to see exactly what's mounted.
  • docker run --rm -v mydata:/data alpine ls -la /data to inspect volume contents.
  • For bind mounts, check SELinux/AppArmor on Linux hosts.
Interviews

Interview checkpoint

Practice

Hands-on lab

Persistent Database with Volumes
30 min · intermediate
In progress
Objectives
  • Create and use named volumes
  • Persist a database across container recreation
  • Back up and restore volume data
  • Use bind mounts for development

Persistent Database with Volumes

30 min · intermediate

0/5 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/3
1

What happens to data in a container's writable layer after docker rm?

2

Which option mounts an in-memory filesystem?

3

Named volumes are removed automatically when you run docker rm.

Quick reference

Cheat sheet

Storage
docker volume create VCreate named volume
-v V:/pathMount named volume
-v /host:/pathBind mount (absolute path)
--tmpfs /pathIn-memory mount
docker volume lsList volumes
docker volume rm VDelete volume
Go deeper

Official documentation