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

TypeStorage LocationManaged ByUse Case
VolumeDocker-managed directoryDockerDatabases, persistent app data
Bind MountAny path on hostYouSharing code during development
tmpfs MountHost RAM (memory)DockerTemporary sensitive data

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:

FeatureVolumeBind Mount
Managed by DockerYesNo
LocationDocker choosesYou choose
Portable across machinesYesNo (path must exist)
Best forProduction dataLocal development
Works with Docker DesktopYesYes (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

CommandWhat it does
docker volume create <name>Create a named volume
docker volume lsList all volumes
docker volume inspect <name>Show volume details
docker volume rm <name>Remove a volume
docker volume pruneRemove all unused volumes
-v name:/pathAttach named volume in docker run
-v /host/path:/container/pathBind mount in docker run
--tmpfs /pathtmpfs 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