Skip to content
intermediate Phase 3 · Docker Volumes & Storage

Volumes & Persistent Data

Create and manage Docker volumes for data persistence.

1h
0 problems
Topic Progress 0%

Why Docker Volumes Matter

Why Docker Volumes Matter

Container filesystems are ephemeral. When a container is removed, all data written to its writable layer is lost. Docker volumes solve this by persisting data outside the container lifecycle.

The Problem

# Start a database container
docker run -d --name pg1 -e POSTGRES_PASSWORD=secret postgres:16

# Create data inside
docker exec pg1 psql -U postgres -c "CREATE TABLE users (id INT, name TEXT);"
docker exec pg1 psql -U postgres -c "INSERT INTO users VALUES (1, 'Alice');"

# Stop and remove container
docker stop pg1 && docker rm pg1

# All data is GONE. The users table no longer exists.
# Starting a new container creates a fresh, empty database.

The Solution

# Start with a named volume
docker run -d --name pg2 \
  -e POSTGRES_PASSWORD=secret \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16

# Create data
docker exec pg2 psql -U postgres -c "CREATE TABLE users (id INT, name TEXT);"
docker exec pg2 psql -U postgres -c "INSERT INTO users VALUES (1, 'Alice');"

# Stop and remove container
docker stop pg2 && docker rm pg2

# Start new container with SAME volume
docker run -d --name pg3 \
  -e POSTGRES_PASSWORD=secret \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16

# Data persists! Query the users table
docker exec pg3 psql -U postgres -c "SELECT * FROM users;"
#  id | name
# ----+-------
#   1 | Alice

Volume Storage Location

Docker volumes are stored on the host filesystem, managed by Docker:

# Default location (Linux)
/var/lib/docker/volumes/

# List volumes
docker volume ls

# Inspect a volume
docker volume inspect pgdata
# {
#   "Mountpoint": "/var/lib/docker/volumes/pgdata/_data",
#   "Driver": "local",
#   "Name": "pgdata"
# }

The data lives at /var/lib/docker/volumes/pgdata/_data on the host. If the Docker host dies, the data is lost unless backed up. For critical data, use cloud-backed volume drivers.

Volume Operations

Volume Operations

Creating Volumes

# Create a named volume
docker volume create mydata

# Create with driver options
docker volume create --driver local \
  --opt type=none \
  --opt device=/data \
  --opt o=bind \
  myvolume

Using Volumes with Containers

# Mount a named volume
docker run -d -v mydata:/app/data myapp

# Read-only volume
docker run -d -v myconfig:/etc/config:ro myapp

# Multiple volumes
docker run -d \
  -v mydata:/app/data \
  -v myconfig:/etc/config:ro \
  -v logs:/var/log \
  myapp

# Anonymous volume (Docker creates a random name)
docker run -d -v /app/data myapp
# Volume name: a1b2c3d4e5f6...

Listing and Inspecting

# List all volumes
docker volume ls
# DRIVER    VOLUME NAME
# local     mydata
# local     pgdata
# local     a1b2c3d4e5f6...

# Inspect volume details
docker volume inspect mydata

# List volumes with size
docker system df -v

Removing Volumes

# Remove a specific volume (must not be in use)
docker volume rm mydata

# Remove all unused volumes
docker volume prune

# Force remove (even if in use - DANGEROUS)
docker volume rm -f mydata

Backup and Restore

# Backup: Run container with volume and host mount
docker run --rm \
  -v pgdata:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/pgdata-backup.tar.gz -C /source .

# Restore: Create volume and extract backup
docker volume create pgdata-restored
docker run --rm \
  -v pgdata-restored:/target \
  -v $(pwd):/backup \
  alpine tar xzf /backup/pgdata-backup.tar.gz -C /target

Copy Data Between Volumes

# Using a temporary container
docker run --rm \
  -v source-vol:/source:ro \
  -v target-vol:/target \
  alpine cp -a /source/. /target/

Volume Drivers and Backends

Volume Drivers and Backends

Local Driver (Default)

The default local driver stores volumes on the Docker host's filesystem:

# Basic local volume
docker volume create --driver local mydata

# Local volume with NFS mount
docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.1.10,rw \
  --opt device=:/exports/data \
  nfs-volume

Cloud Volume Drivers

AWS EBS:

# Install plugin
docker plugin install --grant-all-permissions rexray/ebs

# Create EBS-backed volume
docker volume create --driver rexray/ebs \
  --opt size=100 \
  --opt volumetype=gp3 \
  ebs-volume

# Use with container
docker run -d -v ebs-volume:/data myapp

Azure:

docker plugin install --grant-all-permissions azure/azurefile

# Create Azure File volume
docker volume create --driver azure/azurefile \
  --opt filesharename=myshare \
  --opt storageaccount=mystorageaccount \
  azure-volume

NFS:

docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.1.10,rw \
  --opt device=:/exports/data \
  nfs-data

Volume Labels

# Create with labels
docker volume create --label env=production --label team=backend mydata

# Filter volumes by label
docker volume ls --filter label=env=production

Volume Best Practices

  • Use named volumes for databases and persistent data
  • Use read-only mounts for configuration files
  • Always back up critical volumes before Docker upgrades
  • Use volume drivers for network/cloud storage in production
  • Never store sensitive data in volumes without encryption
  • Use :z or :Z suffix on SELinux systems to fix permission issues