Docker Volumes
The Problem - Data is Lost When a Container is Deleted
By default, everything inside a container is stored in its writable layer. When the container is deleted, all data is gone.
Container running MySQL
/var/lib/mysql <- database files stored here
docker rm -f mysql-container <- container deleted
All database files GONE
Volumes solve this problem by storing data outside the container, on the host machine. The data survives even when the container is deleted.
Three Types of Storage in Docker
Host Machine
/var/lib/docker/volumes/ <- Docker Volumes
/home/irfan/myapp/ <- Bind Mounts
(RAM) <- tmpfs Mounts
Container
/data <- Volume
/app <- Bind Mount
/tmp <- tmpfs
| Type | Storage Location | Managed By | Use Case |
|---|---|---|---|
| Volume | Docker-managed directory | Docker | Databases, persistent app data |
| Bind Mount | Any path on host | You | Sharing code during development |
| tmpfs Mount | Host RAM (memory) | Docker | Temporary sensitive data |
1. Docker Volumes (Recommended)
Docker manages the storage location. You only refer to volumes by name.
docker volume create - Create a Volume
# Create a named volume
docker volume create my-data
# Create with labels
docker volume create --label project=myapp my-data
# Create with a specific driver
docker volume create --driver local my-data
docker volume ls - List Volumes
# List all volumes
docker volume ls
# Filter by driver
docker volume ls --filter "driver=local"
# Filter dangling volumes (not used by any container)
docker volume ls --filter "dangling=true"
# Show only volume names
docker volume ls -q
# Custom format
docker volume ls --format "{{.Name}}\t{{.Driver}}"
Example output:
DRIVER VOLUME NAME
local my-data
local mysql-data
local nginx-logs
docker volume inspect - Detailed Volume Info
# Inspect a volume
docker volume inspect my-data
# Get just the mount point
docker volume inspect --format '{{.Mountpoint}}' my-data
# Get the driver
docker volume inspect --format '{{.Driver}}' my-data
Example output:
[
{
"CreatedAt": "2024-01-01T12:00:00Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-data/_data",
"Name": "my-data",
"Options": {},
"Scope": "local"
}
]
docker volume rm - Remove a Volume
# Remove a volume
docker volume rm my-data
# Remove multiple volumes
docker volume rm my-data mysql-data
# Force remove (even if in use - dangerous!)
docker volume rm -f my-data
docker volume prune - Remove Unused Volumes
# Remove all unused volumes (not attached to any container)
docker volume prune
# Remove without confirmation
docker volume prune -f
# Filter - remove volumes created before a certain time
docker volume prune --filter "until=24h"
Using Volumes with Containers
# Attach a named volume to a container
docker run -d \
--name mysql-db \
-v mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.0
# Attach volume using --mount (verbose but explicit)
docker run -d \
--name mysql-db \
--mount type=volume,source=mysql-data,target=/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.0
# Multiple volumes
docker run -d \
-v mysql-data:/var/lib/mysql \
-v mysql-logs:/var/log/mysql \
mysql:8.0
# Read-only volume
docker run -d \
-v my-config:/app/config:ro \
my-app
Sharing Volumes Between Containers
# Container 1 writes data
docker run -d --name writer -v shared-data:/data ubuntu \
sh -c "while true; do date >> /data/log.txt; sleep 1; done"
# Container 2 reads the same data
docker run -d --name reader -v shared-data:/data ubuntu \
sh -c "tail -f /data/log.txt"
2. Bind Mounts
A bind mount maps a specific path on your host directly into the container. You choose the exact location on your machine.
# Bind mount a local directory into container
docker run -d \
--name my-app \
-v /home/irfan/myapp:/app \
node:20
# Windows path example
docker run -d \
-v C:\Users\irfan\myapp:/app \
node:20
# Using --mount (explicit syntax)
docker run -d \
--mount type=bind,source=/home/irfan/myapp,target=/app \
node:20
# Read-only bind mount
docker run -d \
-v /home/irfan/config:/app/config:ro \
my-app
# Bind current directory (great for development)
docker run -d \
-v $(pwd):/app \
-w /app \
node:20 \
npm start
Bind Mount vs Volume:
| Feature | Volume | Bind Mount |
|---|---|---|
| Managed by Docker | Yes | No |
| Location | Docker chooses | You choose |
| Portable across machines | Yes | No (path must exist) |
| Best for | Production data | Local development |
| Works with Docker Desktop | Yes | Yes (with path sharing) |
3. tmpfs Mounts
Stores data in the host's memory (RAM), not on disk. Data is lost when the container stops. Used for temporary, sensitive data.
# Create a tmpfs mount
docker run -d \
--name tmp-app \
--tmpfs /tmp \
my-app
# Using --mount (explicit)
docker run -d \
--mount type=tmpfs,target=/tmp \
my-app
# With size limit (100MB)
docker run -d \
--mount type=tmpfs,target=/tmp,tmpfs-size=100m \
my-app
# With mode (permissions)
docker run -d \
--mount type=tmpfs,target=/tmp,tmpfs-mode=1770 \
my-app
Backup and Restore Volumes
Backup a Volume
# Run a temporary container that:
# 1. Mounts the volume
# 2. Creates a tar backup in the current directory
docker run --rm \
-v my-data:/source \
-v $(pwd):/backup \
ubuntu \
tar czf /backup/my-data-backup.tar.gz -C /source .
Restore a Volume from Backup
# Create a new volume
docker volume create my-data-restored
# Run a temporary container that extracts the backup into the volume
docker run --rm \
-v my-data-restored:/target \
-v $(pwd):/backup \
ubuntu \
tar xzf /backup/my-data-backup.tar.gz -C /target
Volume in Docker Compose
version: "3.9"
services:
db:
image: mysql:8.0
volumes:
- mysql-data:/var/lib/mysql # named volume
- ./init.sql:/docker-entrypoint-initdb.d/init.sql # bind mount
environment:
MYSQL_ROOT_PASSWORD: secret
app:
image: my-app:1.0
volumes:
- ./src:/app/src # bind mount for development
volumes:
mysql-data: # declares the named volume
Volume Commands Quick Reference
| Command | What it does |
|---|---|
docker volume create <name> | Create a named volume |
docker volume ls | List all volumes |
docker volume inspect <name> | Show volume details |
docker volume rm <name> | Remove a volume |
docker volume prune | Remove all unused volumes |
-v name:/path | Attach named volume in docker run |
-v /host/path:/container/path | Bind mount in docker run |
--tmpfs /path | tmpfs mount in RAM |
FAQ
Should I memorize every Docker command?+
No. Memorize the core workflow first: build, run, list, inspect, logs, exec, stop, remove, and clean up. Then learn specialized commands when you need them.
Is Docker only for developers?+
No. Docker is useful for system administrators, infrastructure engineers, DevOps engineers, cloud engineers, support engineers, and learners who want repeatable labs.
What should I do after reading this guide?+
Run the examples, write down what each command changes, rebuild the workflow with Docker Compose, and then add one CI/CD step that builds the image automatically.
Need help applying Docker in a real project?
Work directly with Muhammad Irfan Aslam for Docker, Linux, DevOps, CI/CD, cloud deployment, or infrastructure troubleshooting support.
Hire Me for Support