Skip to main content

Docker Storage:

 Docker Storage: Volumes and Bind Mounts

📅 Published: Feb 2026
⏱️ Estimated Reading Time: 16 minutes
🏷️ Tags: Docker, Storage, Volumes, Bind Mounts, Data Persistence, Docker Volumes


Introduction: The Storage Problem

Containers are ephemeral by design. When a container is removed, everything written inside it disappears. This is great for stateless applications. But most real applications need to persist data. Databases need to store records. Web applications need to save user uploads. Logs need to be retained.

Docker solves this problem with two storage mechanisms: volumes and bind mounts. Both allow containers to store data outside their writable layer, ensuring data survives container restarts and removals.

This guide explains when to use each type, how to configure them, and best practices for production deployments.


Part 1: Docker Storage Types

The Three Storage Options

Docker provides three ways to manage data in containers:

Storage TypeManaged ByLocationUse Case
VolumesDocker/var/lib/docker/volumes/Production data, databases, shared data
Bind MountsYouAnywhere on hostDevelopment code, config files
tmpfs mountsDockerMemoryTemporary data, secrets

Container Writable Layer

Every container has a writable layer on top of the image layers. When you write data in a container, it goes to this writable layer. But when the container is removed, this layer is lost.

text
┌─────────────────┐
│  Writable Layer │ ← Data here is lost when container is removed
├─────────────────┤
│  Image Layers   │ ← Read-only, shared between containers
└─────────────────┘

Volumes and bind mounts bypass the writable layer. Data written to them persists even after the container is removed.


Part 2: Volumes

What Are Volumes?

Volumes are the preferred way to persist data in Docker. They are completely managed by Docker. Volumes are stored in a part of the host filesystem managed by Docker (/var/lib/docker/volumes/ on Linux). You should not modify these files directly.

Why Volumes Are Preferred

Managed by Docker
Docker handles volume creation, backup, and restoration. You don't need to manage filesystem permissions or locations.

Cross-Platform
Volumes work the same on Linux, Windows, and Mac. Bind mounts have different behaviors across platforms.

Backup and Migration
Docker provides commands to backup and restore volumes. You can easily move volumes between hosts.

Performance
On Linux, volumes have better performance than bind mounts because they use the native filesystem.

Volume Drivers
Volumes support drivers for network storage, cloud storage, and encryption.


Creating and Using Volumes

Create a volume

bash
# Create named volume
docker volume create mydata

# List volumes
docker volume ls

# Inspect volume
docker volume inspect mydata

Use volume in a container

bash
# Mount volume to /data in container
docker run -v mydata:/data alpine touch /data/test.txt

# Another container can access the same data
docker run -v mydata:/data alpine ls /data
# Output: test.txt

Shorthand syntax

bash
# Create and mount in one command
docker run -v myvolume:/app/data nginx

Mount syntax (recommended)
The --mount syntax is more explicit and preferred for complex mounts.

bash
docker run --mount source=mydata,target=/data alpine

Volume Drivers

Volume drivers allow storing data outside the local host.

bash
# Create volume with driver
docker volume create --driver flocker mydata

# Use with cloud storage
docker volume create --driver cloudstor:aws --opt size=10 mydata

Backup and Restore Volumes

Backup a volume

bash
# Run a temporary container that copies volume contents
docker run --rm -v mydata:/source -v $(pwd):/backup alpine \
  tar czf /backup/mydata-backup.tar.gz -C /source .

Restore a volume

bash
# Restore from backup
docker run --rm -v mydata:/target -v $(pwd):/backup alpine \
  tar xzf /backup/mydata-backup.tar.gz -C /target

Removing Volumes

bash
# Remove volume
docker volume rm mydata

# Remove unused volumes
docker volume prune

# Remove all unused volumes
docker volume prune -a

Part 3: Bind Mounts

What Are Bind Mounts?

Bind mounts map a directory or file from the host into the container. You control the exact location on the host. Unlike volumes, bind mounts are not managed by Docker.

When to Use Bind Mounts

Development
Bind mounts allow you to edit code on your host and see changes immediately in the container. No rebuild needed.

Configuration files
You can mount specific configuration files from the host into containers.

Sharing host data
When containers need to access existing data on the host.

Using Bind Mounts

Basic bind mount

bash
# Mount current directory to /app in container
docker run -v $(pwd):/app node:18 npm start

# Mount specific directory
docker run -v /host/data:/container/data nginx

Mount syntax

bash
# Using --mount (recommended)
docker run --mount type=bind,source=$(pwd),target=/app node:18

# Read-only bind mount
docker run --mount type=bind,source=$(pwd),target=/app,readonly node:18

Bind Mount Examples

Development with live reload

bash
# Mount code, run with hot reload
docker run -v $(pwd):/app -p 3000:3000 node:18 npm run dev

Mount configuration file

bash
# Mount custom nginx config
docker run -v /host/nginx.conf:/etc/nginx/nginx.conf:ro -p 80:80 nginx

Mount multiple locations

bash
docker run \
  -v /host/data:/data \
  -v /host/config/app.conf:/app/config/app.conf:ro \
  myapp

Part 4: Volumes vs Bind Mounts

Comparison Table

FeatureVolumesBind Mounts
Managed byDockerYou
Location/var/lib/docker/volumes/Anywhere on host
BackupDocker commandsManual
Cross-platformYesLimited
Performance (Linux)NativeGood
Performance (Mac/Windows)GoodSlower (through VM)
PermissionsDocker managesYou manage
PortabilityHighLow
Use in DockerfileNoNo
Volume driversYesNo

When to Use Volumes

Production databases
Volumes provide better performance and are managed by Docker.

Persistent application data
When data must survive container removal.

Sharing data between containers
Multiple containers can mount the same volume.

Backup and restore
Docker provides built-in backup commands.

When you need volume drivers
For network storage or cloud storage.

When to Use Bind Mounts

Development
Edit code on host, see changes in container without rebuild.

Configuration management
Mount specific config files from host.

Accessing host data
When containers need to read or write to specific host directories.

Testing
Quickly test changes without building images.


Part 5: Advanced Storage Patterns

Pattern 1: Sharing Data Between Containers

Using named volume

bash
# Create volume
docker volume create shared-data

# First container writes data
docker run -v shared-data:/data alpine sh -c "echo hello > /data/file.txt"

# Second container reads data
docker run -v shared-data:/data alpine cat /data/file.txt

Using container volumes (--volumes-from)

bash
# Create data container
docker create -v /data --name data-container alpine

# Other containers share the volume
docker run --volumes-from data-container alpine ls /data

Pattern 2: Database with Persistent Storage

bash
# Create volume for database
docker volume create postgres-data

# Run PostgreSQL with volume
docker run -d \
  --name postgres \
  -e POSTGRES_PASSWORD=secret \
  -v postgres-data:/var/lib/postgresql/data \
  postgres:15

# Data survives container removal
docker stop postgres
docker rm postgres

# New container with same volume retains data
docker run -d \
  --name postgres-new \
  -e POSTGRES_PASSWORD=secret \
  -v postgres-data:/var/lib/postgresql/data \
  postgres:15

Pattern 3: Development Environment

bash
# Bind mount code, volume for dependencies
docker run -it \
  --name dev \
  -v $(pwd):/app \
  -v node_modules:/app/node_modules \
  -p 3000:3000 \
  node:18 /bin/bash

The node_modules volume ensures dependencies persist while code is mounted.

Pattern 4: Log Aggregation

bash
# Create volume for logs
docker volume create app-logs

# Application container writes logs
docker run -d --name app -v app-logs:/var/log/app myapp

# Log processor reads logs
docker run -d --name log-processor -v app-logs:/logs log-processor

Part 6: Permissions and Ownership

The Permission Problem

When you use bind mounts, files keep their host ownership. The container user may not have permission to read or write these files.

Solution 1: Match User IDs

Find the container user ID:

bash
docker run --rm alpine id
# uid=0(root) gid=0(root)

Run container with same UID as host user:

bash
docker run -u $(id -u):$(id -g) -v $(pwd):/app alpine touch /app/test.txt

Solution 2: Change Ownership in Container

bash
docker run -v $(pwd):/app alpine sh -c "chown -R node:node /app && npm start"

Solution 3: Use Dockerfile with User

dockerfile
FROM node:18
WORKDIR /app
RUN chown -R node:node /app
USER node

Solution 4: Use Volumes (No Permission Issues)

Volumes automatically handle permissions correctly. This is another reason to prefer volumes in production.


Part 7: Performance Considerations

Volume Performance

Volumes on Linux use the native filesystem. Performance is excellent—comparable to writing directly to disk.

Bind Mount Performance on Linux

Bind mounts on Linux have good performance. There is minimal overhead compared to volumes.

Bind Mount Performance on Mac/Windows

On Docker Desktop (Mac/Windows), bind mounts go through a virtual machine. Performance can be significantly slower than volumes. For development, this is usually acceptable. For production on Mac/Windows, use volumes.

Optimizing Bind Mount Performance

Use :cached or :delegated flags (Docker Desktop)

bash
# For read-heavy workloads
docker run -v $(pwd):/app:cached node:18

# For write-heavy workloads
docker run -v $(pwd):/app:delegated node:18

Use volumes for dependencies

bash
# Bind mount code, volume for node_modules
docker run -v $(pwd):/app -v node_modules:/app/node_modules node:18

Part 8: Real-World Scenarios

Scenario 1: Production PostgreSQL Database

A production PostgreSQL database needs reliable, persistent storage.

bash
# Create volume
docker volume create postgres-prod

# Run PostgreSQL
docker run -d \
  --name postgres \
  -e POSTGRES_PASSWORD=secure_password \
  -e POSTGRES_DB=myapp \
  -v postgres-prod:/var/lib/postgresql/data \
  --restart unless-stopped \
  postgres:15

# Backup daily
docker run --rm \
  -v postgres-prod:/data \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/postgres-$(date +%Y%m%d).tar.gz -C /data .

Scenario 2: Web Application Development

A developer needs to work on a Node.js application with hot reload.

bash
# Create volume for dependencies
docker volume create app-node-modules

# Run development container
docker run -it \
  --name dev \
  -v $(pwd):/app \
  -v app-node-modules:/app/node_modules \
  -p 3000:3000 \
  -p 9229:9229 \
  node:18 \
  npm run dev

Scenario 3: Nginx with Custom Configuration

A web server needs a custom configuration file and SSL certificates.

bash
# Mount config file (read-only)
# Mount SSL certificates
docker run -d \
  --name nginx \
  -v /host/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v /host/certs:/etc/nginx/certs:ro \
  -p 80:80 \
  -p 443:443 \
  nginx

Scenario 4: Multi-Container Application with Shared Uploads

A web application allows user uploads. The web containers need to share uploaded files.

bash
# Create volume for uploads
docker volume create uploads

# Run web containers with shared volume
docker run -d --name web1 -v uploads:/app/uploads -p 8080:80 mywebapp
docker run -d --name web2 -v uploads:/app/uploads -p 8081:80 mywebapp

# Run background processor that reads uploads
docker run -d --name processor -v uploads:/app/uploads myprocessor

Part 9: Troubleshooting

Container Can't Write to Bind Mount

Problem: Permission denied when writing to bind mount.

Check permissions:

bash
# Check host file permissions
ls -la $(pwd)

# Check container user
docker run --rm alpine id

Fix:

bash
# Run with same user
docker run -u $(id -u):$(id -g) -v $(pwd):/app alpine touch /app/test.txt

# Or change permissions in container
docker run -v $(pwd):/app alpine sh -c "chown -R 1000:1000 /app && touch /app/test.txt"

Volume Won't Delete

Problem: Volume cannot be removed because it's in use.

bash
# Find containers using volume
docker ps -a --filter volume=mydata

# Remove containers
docker rm container-id

# Remove volume
docker volume rm mydata

Bind Mount Performance Slow

Problem: File operations in bind mount are slow (Docker Desktop).

Solutions:

  • Use volumes instead of bind mounts

  • Add :cached or :delegated flags

  • Use Docker Desktop settings to improve performance

  • Consider moving to Linux for production

Lost Data After Container Removal

Problem: Container data disappeared after removal.

Check if volume was used:

bash
# List volumes
docker volume ls

# Check if container had volume mount
docker inspect container | jq '.[0].Mounts'

Prevention: Always use volumes for persistent data.


Summary

Storage TypeBest ForKey Characteristics
VolumesProduction data, databasesDocker-managed, portable, better performance
Bind MountsDevelopment, config filesHost-managed, direct access, convenient

Volumes are the recommended choice for production persistent data. They are managed by Docker, portable across platforms, and provide better performance.

Bind mounts are excellent for development and for mounting specific configuration files. They give you direct access to files on the host.


Practice Questions

  1. What is the difference between a volume and a bind mount?

  2. Why are volumes preferred for production databases?

  3. How do you create a named volume and mount it to a container?

  4. A developer needs to edit code on their laptop and see changes immediately in a container. Which storage type should they use?

  5. How do you backup a volume to a tar file?


Learn More

Practice Docker storage with hands-on exercises in our interactive labs:
https://devops.trainwithsky.com/

Comments

Popular posts from this blog

Introduction to Terraform – The Future of Infrastructure as Code

  Introduction to Terraform – The Future of Infrastructure as Code In today’s fast-paced DevOps world, managing infrastructure manually is outdated . This is where Terraform comes in—a powerful Infrastructure as Code (IaC) tool that allows you to define, provision, and manage cloud infrastructure efficiently . Whether you're working with AWS, Azure, Google Cloud, or on-premises servers , Terraform provides a declarative, automation-first approach to infrastructure deployment. Shape Your Future with AI & Infinite Knowledge...!! Read In-Depth Tech & Self-Improvement Blogs http://www.skyinfinitetech.com Watch Life-Changing Videos on YouTube https://www.youtube.com/@SkyInfinite-Learning Transform Your Skills, Business & Productivity – Join Us Today! In today’s digital-first world, agility and automation are no longer optional—they’re essential. Companies across the globe are rapidly shifting their operations to the cloud to keep up with the pace of innovatio...

📊 Monitoring & Logging in Kubernetes – Tools like Prometheus, Grafana, and Fluentd

  Monitoring & Logging in Kubernetes – Tools like Prometheus, Grafana, and Fluentd Monitoring and logging are essential for maintaining a healthy and well-performing Kubernetes cluster. In this guide, we’ll cover why monitoring is important, key monitoring tools like Prometheus and Grafana, and logging tools like Fluentd to help you gain visibility into your cluster’s performance and logs. Shape Your Future with AI & Infinite Knowledge...!! Want to Generate Text-to-Voice, Images & Videos? http://www.ai.skyinfinitetech.com Read In-Depth Tech & Self-Improvement Blogs http://www.skyinfinitetech.com Watch Life-Changing Videos on YouTube https://www.youtube.com/@SkyInfinite-Learning Transform Your Skills, Business & Productivity – Join Us Today! 🚀 Introduction In today’s fast-paced cloud-native environment, Kubernetes has emerged as the de-facto container orchestration platform. But deploying and managing applications in Kubernetes is just half the ba...

🔒 Kubernetes Security – RBAC, Network Policies, and Secrets Management

  Kubernetes Security – RBAC, Network Policies, and Secrets Management Security is a critical aspect of managing Kubernetes clusters. In this guide, we'll cover essential security mechanisms like Role-Based Access Control (RBAC) , Network Policies , and Secrets Management to help you secure your Kubernetes environment effectively. Shape Your Future with AI & Infinite Knowledge...!! Want to Generate Text-to-Voice, Images & Videos? http://www.ai.skyinfinitetech.com Read In-Depth Tech & Self-Improvement Blogs http://www.skyinfinitetech.com Watch Life-Changing Videos on YouTube https://www.youtube.com/@SkyInfinite-Learning Transform Your Skills, Business & Productivity – Join Us Today! 🚀 Introduction: Why Kubernetes Security Is Non-Negotiable As Kubernetes becomes the backbone of modern cloud-native infrastructure, security is no longer optional—it’s mission-critical . With multiple moving parts like containers, pods, services, nodes, and more, Kuberne...