Docker Volumes
LEVEL 0
The Problem
You need to run a PostgreSQL database in a container. The data must persist even if the container is recreated.
You could use bind mounts (map a host directory), but that has issues:
- Host filesystem permissions can conflict
- Not portable across different hosts
- Harder to backup and migrate
- Host directory structure leaks into container world
You want Docker to manage the storage for you. You want a solution that lets Docker manage the details.
This is what Docker volumes provide.
LEVEL 1
The Concept — The Warehouse for Containers
The Concept
Imagine a shipping company (Docker) that runs cargo ships (containers).
Each ship carries cargo temporarily. When the ship docks, unloads, and leaves, the cargo should go somewhere permanent.
The company builds warehouses near the port. These warehouses are managed by the shipping company. When a ship arrives, it can store or retrieve cargo from a warehouse.
Ships come and go. Warehouses persist.
Docker volumes are these warehouses. Docker creates and manages them. Containers can mount volumes to store data. When containers are removed, volumes remain.
LEVEL 2
The Mechanics — How Docker Volumes Work
The Mechanics
Creating a volume:
docker volume create pgdata
Docker creates a directory at /var/lib/docker/volumes/pgdata/.
Mounting a volume in a container:
docker run -d \
--name postgres \
-v pgdata:/var/lib/postgresql/data \
postgres:15
This mounts the volume pgdata at /var/lib/postgresql/data inside the container.
PostgreSQL writes its database files to /var/lib/postgresql/data, which is actually stored in the Docker volume on the host.
What happens:
- Container writes file to
/var/lib/postgresql/data/file.db - Docker redirects this write to
/var/lib/docker/volumes/pgdata/_data/file.dbon the host - The file persists on the host filesystem, managed by Docker
Removing the container:
docker stop postgres
docker rm postgres
The volume pgdata still exists. Data is safe.
Starting a new container with the same volume:
docker run -d \
--name postgres-new \
-v pgdata:/var/lib/postgresql/data \
postgres:15
PostgreSQL starts and finds all its data still there. No data loss.
LEVEL 3
Volume Management Commands
List volumes:
docker volume ls
Inspect a volume:
docker volume inspect pgdata
Shows where the volume is stored on the host:
[
{
"Name": "pgdata",
"Mountpoint": "/var/lib/docker/volumes/pgdata/_data",
...
}
]
View volume data (on host):
sudo ls -la /var/lib/docker/volumes/pgdata/_data
You’ll see the PostgreSQL data files.
Remove a volume:
docker volume rm pgdata
Warning: This deletes all data in the volume. Only do this if you’re sure.
Remove all unused volumes:
docker volume prune
Be careful—this removes volumes not attached to any container.
Create volume with specific driver:
docker volume create --driver local --opt type=nfs --opt o=addr=192.168.1.100 nfs-volume
This creates a volume backed by NFS instead of local storage.
LEVEL 4
Anonymous vs. Named Volumes
Named volume:
docker run -v mydata:/app/data myimage
You explicitly create and name the volume (mydata). Easy to reference later.
Anonymous volume:
docker run -v /app/data myimage
Docker creates a volume with a random ID (like a7f3c2b1e9d4...). Harder to manage.
Best practice: Always use named volumes in production.
LEVEL 5
Volume Drivers and Plugins
Docker volumes can be backed by different storage systems via drivers:
Local driver (default):
Stores data on the host filesystem.
Cloud drivers:
- AWS EBS: Amazon Elastic Block Store
- Google Persistent Disk
- Azure Disk Storage
Network drivers:
- NFS: Network File System
- CIFS/SMB: Windows file shares
- GlusterFS: Distributed storage
Example: NFS volume
docker volume create \
--driver local \
--opt type=nfs \
--opt o=addr=nfs-server.example.com,rw \
--opt device=:/path/to/share \
nfs-data
docker run -v nfs-data:/app/data myimage
Now multiple containers on different hosts can share the same NFS volume.