💾 Docker Volumes — Complete Guide

Volumes, bind mounts, tmpfs — data persistence patterns, backups, and real-world usage.

Docker Storage Overview

By default, container data is stored in the container's writable layer and lost when the container is removed. Docker provides three mount types for persistent storage: volumes, bind mounts, and tmpfs mounts.

Best Practice: Use volumes for production data persistence. They're managed by Docker, work across platforms, and offer better performance than bind mounts on Docker Desktop.

Three Mount Types

Docker Host
Docker Volume
/var/lib/docker/volumes
Managed by Docker
↓
Container
Host Directory
/home/user/data
Bind Mount
↓
Container
RAM (tmpfs)
Memory Only
Temporary
↓
Container

Key Concepts

Persistence

Data survives container restarts and deletions when stored in volumes or bind mounts.

Isolation

Container storage layer is isolated from volumes - data doesn't count toward container size.

Sharing

Multiple containers can mount the same volume simultaneously for data sharing.

Performance

Volumes offer native disk performance. tmpfs offers RAM speed. Bind mounts vary by platform.

Management

Docker CLI commands manage volumes. Host OS manages bind mount directories.

Portability

Volumes work consistently across Docker hosts. Bind mounts depend on host filesystem structure.

Container Storage Layers

1
Read-Only Image Layers - Base OS, dependencies, application code (immutable)
2
Container Writable Layer - Changes made during runtime (lost when container removed)
3
Mounted Volumes - Persistent storage bypassing container storage layer

Common Volume Commands

# Create a volume
docker volume create my-volume

# List all volumes
docker volume ls

# Inspect volume details
docker volume inspect my-volume

# Remove a volume
docker volume rm my-volume

# Remove all unused volumes
docker volume prune

# Run container with volume
docker run -v my-volume:/app/data nginx

# Run container with bind mount
docker run -v /host/path:/container/path nginx

Docker Volumes

Volumes are the preferred mechanism for persisting data in Docker. They're completely managed by Docker, stored in a dedicated directory on the host (/var/lib/docker/volumes/ on Linux), and isolated from core host functionality.

Recommendation: Always use volumes for production databases, application data, and any content that must persist beyond container lifecycle.

Volume Architecture

Docker Host Filesystem
↓
/var/lib/docker/volumes/
Docker-Managed Storage Area
my-volume
/_data/
↓
Container A
/app/data
db-volume
/_data/
↓
Container B
/var/lib/mysql

How Volumes Work

1. Volume Creation

Created explicitly with docker volume create or automatically when container starts with -v flag.

2. Docker Management

Docker handles storage location, permissions, and lifecycle independently of containers.

3. Mount Point

Volume mounted to specific directory inside container. Multiple containers can share same volume.

4. Data Persistence

Data remains even after container deletion. Must explicitly run docker volume rm to delete.

5. Named vs Anonymous

Named volumes have user-defined names. Anonymous volumes get random UUIDs.

6. Pre-population

If mount point contains data in image, that data is copied to new volume on first mount.

Volume Types

Named Volumes

  • User-friendly names (my-app-data)
  • Easy to reference and manage
  • Ideal for production use
  • Can be shared between containers
  • Created with: docker volume create name

Anonymous Volumes

  • Auto-generated UUID names
  • Created implicitly with -v flag
  • Harder to track and manage
  • Useful for temporary data
  • Often orphaned after container removal

Advantages & Limitations

✓ Advantages

  • Managed by Docker - consistent across platforms
  • Works on Docker Desktop (Mac/Windows)
  • Can be backed up and migrated easily
  • More secure than bind mounts
  • Better performance on Mac/Windows
  • Support for volume drivers (cloud storage)
  • Can pre-populate from container image

✗ Limitations

  • Less transparent than bind mounts
  • Host path not directly visible
  • Requires Docker CLI to access
  • Harder to inspect content directly
  • Anonymous volumes can accumulate

Usage Examples

# Create named volume
docker volume create postgres-data

# Run container with named volume
docker run -d --name db \
-v postgres-data:/var/lib/postgresql/data \
postgres:latest

# Anonymous volume (auto-created)
docker run -d -v /app/data nginx

# Using --mount (long syntax, more explicit)
docker run -d --name web \
--mount source=web-data,target=/usr/share/nginx/html \
nginx

# Inspect volume location
docker volume inspect postgres-data

# Share volume between containers
docker run -d --name app1 -v shared-data:/data alpine
docker run -d --name app2 -v shared-data:/data alpine

# Read-only volume mount
docker run -d -v my-volume:/data:ro nginx

Common Use Cases

Database Storage

PostgreSQL, MySQL, MongoDB - persist database files across container restarts.

Application Data

User uploads, generated files, caches that must survive container updates.

Shared Storage

Multiple containers accessing same data - logs, shared configs, file processing.

Backup Sources

Centralized location for backing up critical application data.

Warning: Always use named volumes for production. Anonymous volumes can be accidentally deleted with docker volume prune, causing data loss.

Bind Mounts

Bind mounts link a specific file or directory on the host to a container location. They provide direct, immediate synchronization between host and container filesystems. Ideal for development workflows where you need real-time code updates without rebuilding images.

Security Note: Bind mounts give containers direct access to host filesystem. This can be a security risk. Use carefully in production.

Bind Mount Architecture

Host Filesystem
/home/user/project
Source Code
↓
Real-time sync
↓
Container
/app
/etc/nginx
Config Files
↓
Direct access
↓
Container
/etc/nginx

How Bind Mounts Work

1. Direct Mapping

Specific host path mapped directly to container path. Must use absolute paths.

2. Immediate Sync

Changes on host appear instantly in container and vice versa. No copy operation.

3. Host Dependency

Requires exact path to exist on host. Not managed by Docker.

4. File Permissions

Host file permissions apply. Container processes must have appropriate access rights.

5. Overwrites Container Data

If mount path contains data in image, host directory content takes precedence.

6. Platform Differences

Performance varies by platform. Slower on Docker Desktop (Mac/Windows) due to filesystem translation.

Advantages & Limitations

✓ Advantages

  • Direct, real-time file access
  • Perfect for development workflows
  • Easy to inspect and edit files
  • No Docker commands needed to access data
  • Can mount specific files (not just dirs)
  • Useful for config file injection

✗ Limitations

  • Reduced portability - host-dependent paths
  • Security risk - direct host access
  • Performance issues on Mac/Windows
  • Manual path management required
  • Can break container isolation
  • Not recommended for production

Usage Examples

# Basic bind mount (short syntax)
docker run -d -v /host/path:/container/path nginx

# Development: Mount source code
docker run -d --name dev-app \
-v $(pwd)/src:/app/src \
-p 3000:3000 \
node:latest

# Mount single config file
docker run -d \
-v /home/user/nginx.conf:/etc/nginx/nginx.conf:ro \
nginx

# Using --mount (long syntax, more explicit)
docker run -d \
--mount type=bind,source=/host/data,target=/app/data \
alpine

# Read-only bind mount
docker run -d -v /host/config:/app/config:ro nginx

# Mount with propagation mode
docker run -d \
--mount type=bind,source=/host/data,target=/data,bind-propagation=shared \
ubuntu

Common Use Cases

Development Environments

Mount source code for live reload without rebuilding images. Edit locally, run in container.

Configuration Files

Inject host configs into containers. Update configs without container restart.

Log Access

Write container logs to host directory for easy monitoring and analysis.

Host Tool Access

Share Docker socket (/var/run/docker.sock) or other host resources with containers.

Bind Mount vs Volume Decision

Scenario Use Bind Mount Use Volume
Development ✓ Source code sync Database data
Production Config files only ✓ All persistent data
Host Integration ✓ Need host tools/files Isolated storage
Performance Linux hosts only ✓ All platforms
Portability Low ✓ High

tmpfs Mounts

tmpfs mounts store data in the host system's memory (RAM) only. They provide the fastest I/O performance but are temporary - all data is lost when the container stops. Perfect for sensitive information that shouldn't be persisted to disk or temporary caches requiring maximum speed.

Linux Only: tmpfs mounts are only available on Linux hosts. Not supported on Docker Desktop for Mac or Windows.

tmpfs Architecture

Docker Host
↓
RAM (System Memory)
Volatile Storage
↓
Container A
/tmp/cache
Data lost on stop
↓
Container B
/run/secrets
Data lost on stop

How tmpfs Works

1. Memory Storage

Data stored entirely in host's RAM. No disk I/O - fastest possible performance.

2. Temporary Nature

All data automatically deleted when container stops. Perfect for temporary files.

3. Size Limits

Limited by available system memory. Can set explicit size limits to prevent OOM issues.

4. No Persistence

Zero disk footprint. Data never written to storage layer. Automatic cleanup.

5. Security Benefits

Sensitive data never hits disk. Reduces risk of data leaks from disk forensics.

6. Platform Limitation

Linux only. Uses native tmpfs filesystem. Not available on Docker Desktop.

Advantages & Limitations

✓ Advantages

  • Extremely fast - RAM speed I/O
  • Automatic cleanup on container stop
  • Ideal for sensitive data (passwords, keys)
  • No disk space consumption
  • Better security - data never on disk
  • Perfect for temporary caches

✗ Limitations

  • Linux hosts only (no Mac/Windows)
  • Data lost on container stop
  • Limited by available RAM
  • Not suitable for persistent data
  • Can cause OOM if overused
  • Can't be shared between hosts

Usage Examples

# Basic tmpfs mount (short syntax)
docker run -d --tmpfs /app/cache nginx

# tmpfs with size limit (default unlimited)
docker run -d --tmpfs /tmp:rw,size=100m,mode=1777 nginx

# Using --mount (long syntax, more options)
docker run -d \
--mount type=tmpfs,destination=/app/tmp,tmpfs-size=104857600 \
ubuntu

# tmpfs with specific mode (permissions)
docker run -d \
--mount type=tmpfs,destination=/run/secrets,tmpfs-mode=1700 \
alpine

# Multiple tmpfs mounts
docker run -d \
--tmpfs /tmp \
--tmpfs /app/cache:rw,size=50m \
nginx

# Verify tmpfs mount
docker exec container-name df -h /app/cache

tmpfs Options

Option Description Example
tmpfs-size Size limit in bytes (default: unlimited) tmpfs-size=104857600 (100MB)
tmpfs-mode File mode in octal (default: 1777) tmpfs-mode=1700 (owner only)
rw / ro Read-write or read-only --tmpfs /tmp:ro

Common Use Cases

Sensitive Credentials

Store API keys, passwords, tokens temporarily. Never written to disk.

Session Data

User sessions, temporary auth tokens. Fast access, automatic expiry.

High-Speed Caches

Application caches requiring maximum I/O speed. RAM latency vs disk.

Build Artifacts

Temporary compilation outputs, intermediate files during build processes.

Testing Data

Temporary test files that don't need persistence. Clean slate every run.

Swap Space

Container-specific temporary storage for memory-intensive operations.

Memory Warning: Be careful with tmpfs size. Excessive tmpfs usage can lead to out-of-memory (OOM) errors and container crashes.

Volume Drivers & Plugins

Volume drivers extend Docker's storage capabilities beyond local filesystem. They enable volumes to be stored on remote hosts, cloud storage, network filesystems, and specialized storage systems. Critical for production deployments requiring high availability, backup, and distributed storage.

Key Concept: The default "local" driver stores volumes on the Docker host. Third-party drivers enable external storage solutions like AWS EBS, Azure Files, NFS, and more.

Volume Driver Architecture

Docker Container
↓
Volume (managed by driver)
↓
Local Driver
Host Disk
↓
NFS Driver
Network Storage
↓
AWS EBS
Cloud Storage
↓
Azure Files
Cloud Storage

Popular Volume Drivers

Driver Storage Backend Use Case
local Host filesystem Default - single-host deployments
nfs Network File System Shared storage across multiple hosts
rexray/ebs AWS Elastic Block Store AWS cloud persistent storage
azure-file Azure File Storage Microsoft Azure cloud storage
gce-docker Google Persistent Disk Google Cloud Platform storage
vieux/sshfs SSH Filesystem Remote host storage via SSH
convoy Multiple backends Backup, snapshot, restore features
portworx Distributed storage Enterprise container storage platform

Local Driver Options

Default Storage

Stores volumes in /var/lib/docker/volumes/ with simple directory structure.

Mount Options

Supports type, device, and o parameters for advanced local mounting.

NFS Mount

Local driver can mount NFS shares as Docker volumes.

CIFS/SMB Support

Can mount Windows shares (CIFS) using local driver with options.

Usage Examples

# Default local driver (implicit)
docker volume create my-volume

# Explicit local driver
docker volume create --driver local my-local-volume

# NFS volume using local driver
docker volume create --driver local \
--opt type=nfs \
--opt o=addr=192.168.1.100,rw \
--opt device=:/path/to/dir \
nfs-volume

# CIFS/SMB volume
docker volume create --driver local \
--opt type=cifs \
--opt device=//server/share \
--opt o=username=user,password=pass \
smb-volume

# AWS EBS with RexRay driver
docker volume create --driver rexray/ebs \
--name my-ebs-volume \
--opt size=10

# Run container with driver-based volume
docker run -d -v my-ebs-volume:/data nginx

# List volumes by driver
docker volume ls --filter driver=local

RexRay Driver Example (AWS EBS)

# Install RexRay plugin
docker plugin install rexray/ebs \
EBS_ACCESSKEY=AKIAIOSFODNN7EXAMPLE \
EBS_SECRETKEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

# Create EBS-backed volume
docker volume create --driver rexray/ebs \
--name postgres-data \
--opt size=20

# Run database with EBS volume
docker run -d --name postgres \
--volume-driver rexray/ebs \
--mount src=postgres-data,target=/var/lib/postgresql/data \
postgres:latest

When to Use Volume Drivers

Multi-Host Deployments

Docker Swarm or Kubernetes needing shared storage across nodes.

Cloud Storage Integration

Leverage AWS EBS, Azure Disks, GCP Persistent Disks for cloud-native apps.

High Availability

Replicated storage backends ensuring data availability during host failures.

Enterprise Storage

Integration with NetApp, EMC, or other enterprise storage systems.

Backup & Snapshots

Drivers offering built-in backup, snapshot, and restore capabilities.

Performance Requirements

SSD-backed cloud storage for high-IOPS database workloads.

Plugin Management: Volume driver plugins require installation and configuration. Always test in non-production environments first.

Volume Backup & Restore

Backing up Docker volumes is critical for disaster recovery, data migration, and testing. Docker volumes can be backed up by creating temporary containers that mount the volume and use tar or application-specific tools to create archives.

Best Practice: For databases, use application-specific backup tools (pg_dump, mysqldump, mongodump) for consistency guarantees. Generic tar backups may capture inconsistent state.

Backup Methods Comparison

Method Pros Cons Best For
Application-Specific Consistent, tested, reliable Tool-dependent, requires knowledge Databases (pg_dump, mysqldump)
Volume Copy (tar) Simple, works for any volume May be inconsistent, large files File-based data, static content
Volume-to-Volume Fast, stays in Docker Still on same host, not true backup Quick snapshots, testing
Third-Party Tools Automated, scheduled, cloud upload Additional dependencies Production environments

Generic Volume Backup (tar method)

# Backup volume to tar file
docker run --rm \
-v my-volume:/data \
-v $(pwd):/backup \
ubuntu tar czf /backup/my-volume-backup.tar.gz -C /data .

# Alternative: Stop container first for consistency
docker stop my-app
docker run --rm -v my-volume:/data -v $(pwd):/backup \
ubuntu tar czf /backup/my-volume-backup.tar.gz -C /data .
docker start my-app

# Restore volume from tar backup
docker run --rm \
-v my-volume:/data \
-v $(pwd):/backup \
ubuntu bash -c "cd /data && tar xzf /backup/my-volume-backup.tar.gz"

# Verify backup file
tar tzf my-volume-backup.tar.gz | head

Database-Specific Backups

# PostgreSQL backup
docker exec postgres-container \
pg_dump -U username dbname > backup.sql

# PostgreSQL backup (all databases)
docker exec postgres-container \
pg_dumpall -U postgres > backup-all.sql

# PostgreSQL restore
docker exec -i postgres-container \
psql -U username dbname < backup.sql

# MySQL backup
docker exec mysql-container \
mysqldump -u root -p'password' dbname > backup.sql

# MySQL restore
docker exec -i mysql-container \
mysql -u root -p'password' dbname < backup.sql

# MongoDB backup
docker exec mongo-container \
mongodump --out /backup --gzip

# MongoDB restore
docker exec mongo-container \
mongorestore --gzip /backup

Volume-to-Volume Copy

# Create new volume
docker volume create my-volume-backup

# Copy data from one volume to another
docker run --rm -i -t \
-v my-volume:/from \
-v my-volume-backup:/to \
ubuntu bash -c "cd /from && cp -av . /to"

# Alternative: Use rsync for incremental copies
docker run --rm \
-v my-volume:/source:ro \
-v backup-volume:/dest \
ubuntu rsync -av /source/ /dest/

Automated Backup Workflow

1
Stop Application (Optional) - Stop container to ensure data consistency
2
Create Backup - Use tar or application-specific tool to create archive
3
Compress & Encrypt - Compress backup file and optionally encrypt
4
Upload to Remote - Transfer backup to external server, S3, or cloud storage
5
Verify Backup - Test restore on non-production environment to ensure integrity
6
Restart Application - Start container and verify normal operation

Backup to Cloud Storage

# Backup to AWS S3
docker run --rm \
-v my-volume:/data:ro \
-e AWS_ACCESS_KEY_ID=your_key \
-e AWS_SECRET_ACCESS_KEY=your_secret \
amazon/aws-cli s3 sync /data s3://my-bucket/backups/$(date +%Y-%m-%d)/

# Backup with encryption to S3
docker run --rm -v my-volume:/data:ro ubuntu tar czf - -C /data . | \
openssl enc -aes-256-cbc -salt -pass pass:mypassword | \
aws s3 cp - s3://my-bucket/backup-$(date +%Y-%m-%d).tar.gz.enc

# Scheduled backup with cron (on host)
# Add to crontab: 0 2 * * * /path/to/backup-script.sh
# backup-script.sh contains backup commands above

Best Practices

Regular Schedule

Automate backups with cron or orchestration tools. Daily at minimum for production data.

Test Restores

Regularly test restore process. Backups are useless if you can't restore from them.

Off-Site Storage

Store backups on different server or cloud storage. Protect against host failure.

Retention Policy

Keep multiple backup versions. Follow 3-2-1 rule: 3 copies, 2 different media, 1 off-site.

Encryption

Encrypt sensitive data backups before upload. Use tools like gpg or openssl.

Monitoring

Monitor backup job success/failure. Alert on backup failures immediately.

Consistency Warning: Backing up live databases with tar may result in corrupted backups. Always prefer application-specific backup tools or stop containers during backup.

Mount Types Comparison

Choose the right mount type based on persistence requirements, performance needs, security constraints, and deployment environment.

Comprehensive Feature Matrix

Feature Volumes Bind Mounts tmpfs Mounts
Managed By Docker Host OS Host OS (RAM)
Data Persistence ✓ Yes ✓ Yes ✗ No (RAM only)
Platform Support All (Linux, Mac, Windows) All (Linux, Mac, Windows) Linux only
Performance Excellent (best on Mac/Win) Excellent (Linux), Slower (Mac/Win) Fastest (RAM speed)
Path Specification Volume name only Absolute host path required Container path only
Pre-population ✓ From container image ✗ Host content takes precedence ✗ Empty on creation
Sharing Between Containers ✓ Easy (name reference) ✓ Possible (same host path) ✗ Per-container only
Backup/Migration Easy (Docker CLI) Depends on host setup Not applicable (temporary)
Security Good isolation Exposes host filesystem Best (never on disk)
Volume Drivers ✓ Supported (NFS, cloud, etc.) ✗ Not applicable ✗ Not applicable
Portability High Low (host-dependent) Medium (Linux only)
Swarm Support ✓ Yes Limited ✓ Yes (per-node)
Storage Location /var/lib/docker/volumes/ User-defined host path System memory (RAM)

Decision Matrix: When to Use Each Type

Use Volumes When:

  • Production data persistence
  • Database storage (PostgreSQL, MySQL, MongoDB)
  • Multi-container data sharing
  • Cloud or network storage needed
  • Running on Docker Desktop (Mac/Windows)
  • Need consistent performance across platforms

Use Bind Mounts When:

  • Local development workflows
  • Source code live reload
  • Sharing host config files
  • Need direct host file access
  • Docker socket sharing (/var/run/docker.sock)
  • Host-specific integrations

Use tmpfs When:

  • Sensitive data (passwords, keys, tokens)
  • Session storage
  • High-speed caches
  • Temporary build artifacts
  • Data that shouldn't persist
  • Running on Linux hosts

Performance Comparison

Read/Write Performance (Best to Slowest):

1. tmpfs
(RAM speed)
→ 2. Volumes
(Disk I/O)
→ 3. Bind Mounts
(Linux: fast)
(Mac/Win: slow)

*Bind mounts on Docker Desktop use filesystem translation layer (osxfs/grpcfuse) causing significant overhead

Security Comparison

Most Secure

  • tmpfs - Never written to disk, automatic cleanup
  • Volumes - Docker-managed, isolated from host

Least Secure

  • Bind Mounts - Direct host access, potential privilege escalation

Real-World Scenarios

Scenario Recommended Mount Why
Production Database Volume Persistence, performance, backup support
Node.js Development Bind Mount Live code reload, instant changes
API Secrets tmpfs Security - never persisted to disk
Application Logs Volume or Bind Mount Volume for isolation, Bind for host access
Static Assets (CDN) Volume Persistence, can migrate to cloud storage
Build Cache tmpfs or Volume tmpfs for speed, Volume for persistence
Config Files Bind Mount Easy updates from host without rebuild
User Uploads Volume (cloud driver) Scalability, S3/Azure integration

Quick Reference Decision Tree

Question 1: Does data need to persist after container stops?
NO → Use tmpfs (fastest, Linux only)
YES → Continue to Question 2

Question 2: Are you in development or production?
DEVELOPMENT → Bind mount for source code, Volume for databases
PRODUCTION → Use Volume (always)

Question 3: Running on Docker Desktop (Mac/Windows)?
YES → Use Volume (much better performance)
NO → Volume or Bind mount both work well

Question 4: Need to share data between containers?
YES → Use Volume (easy sharing by name)
NO → Any mount type works

Question 5: Need cloud storage integration?
YES → Use Volume with driver plugin (rexray, azure, etc.)
NO → Default local driver is fine