Docker Persistent Volumes and Data Management

4 Nov 2026, 11:2715 min readby ITYantra Admin

Complete guide to Docker persistent volumes including named volumes, bind mounts, volume drivers, backup, and data management for stateful containers.

# Docker Persistent Volumes and Data Management

Introduction

Docker containers are ephemeral by default—data written inside a container is lost when the container is removed. Docker provides volumes and bind mounts for persistent data storage. This tutorial covers named volumes, bind mounts, volume drivers, backup/restore, and data management patterns.

Learning Objectives

By the end of this tutorial, you will be able to:

  • Understand Docker storage options (volumes, bind mounts, tmpfs)
  • Create and manage named volumes
  • Use bind mounts for development
  • Configure volume drivers
  • Backup and restore volume data
  • Manage data for stateful containers (databases)

Technical Background

Docker Storage Options

| Type | Description | Use Case | |------|-------------|----------| | Named Volume | Managed by Docker, stored in Docker area | Production databases, persistent data | | Bind Mount | Maps host directory to container | Development, config files | | tmpfs | In-memory mount | Temporary data, high-performance |

Volume Architecture

Host: /var/lib/docker/volumes/mydata/_data
             |
             | (Docker manages)
             v
Container: /app/data (mounted)

Prerequisites

  • Docker installed and running

Hardware and Software Requirements

| Component | Requirement | |-----------|-------------| | Docker | v24+ |

Step-by-Step Implementation

Phase 1: Named Volumes

# Create named volume
docker volume create my-data

# List volumes
docker volume ls

# Inspect volume
docker volume inspect my-data

# Run container with volume
docker run -d \
  -v my-data:/var/lib/mysql \
  --name mysql \
  mysql:8.0

# Remove container, keep volume
docker rm mysql

# Volume still exists
docker volume ls

# Remove volume
docker volume rm my-data

Phase 2: Bind Mounts

# Run container with bind mount
docker run -d \
  -v /home/user/app:/app \
  --name myapp \
  nginx:latest

# Run with read-only bind mount
docker run -d \
  -v /home/user/config:/etc/app:ro \
  --name myapp \
  nginx:latest

# SELinux context (if needed)
docker run -d \
  -v /home/user/app:/app:Z \
  --name myapp \
  nginx:latest

Phase 3: Volume in Docker Compose

# docker-compose.yml
version: '3.8'
services:
  db:
    image: postgres:15
    volumes:
      - db_data:/var/lib/postgresql/data
  web:
    build: .
    volumes:
      - ./code:/app:ro
volumes:
  db_data:
# Start with compose
docker compose up -d

# Volume persists across container recreation
docker compose down
docker compose up -d

Phase 4: Backup and Restore

#### Backup Volume

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

#### Restore Volume

# Create new volume
docker volume create my-data-restored

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

#### Backup Container Data

# Backup data from running container
docker run --rm \
  --volumes-from mysql \
  -v $(pwd):/backup \
  alpine \
  tar czf /backup/mysql-backup.tar.gz /var/lib/mysql

Phase 5: Volume Drivers

# List available volume drivers
docker volume ls --format '{{.Driver}}'

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

# Use volume in container
docker run -d \
  -v nfs-volume:/data \
  --name myapp \
  nginx:latest

Phase 6: Database Data Management

#### PostgreSQL with Volume

# docker-compose.yml
version: '3.8'
services:
  postgres:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: example
      POSTGRES_DB: myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
volumes:
  postgres_data:
# Start database
docker compose up -d postgres

# Backup database
docker exec postgres pg_dumpall -U postgres > backup.sql

# Restore database
cat backup.sql | docker exec -i postgres psql -U postgres

#### MySQL with Volume

services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: myapp
    volumes:
      - mysql_data:/var/lib/mysql
    ports:
      - "3306:3306"
volumes:
  mysql_data:

Phase 7: Volume Cleanup

# Remove unused volumes
docker volume prune

# Remove all unused volumes (force)
docker volume prune -f

# Remove volume with container
docker rm -v myapp

# Check volume usage
docker system df -v

Expected Output

  • Named volumes created and used
  • Bind mounts configured for development
  • Backup and restore procedures working
  • Database data persisted across container restarts

Verification Procedures

| Check | Command | Expected Result | |-------|---------|-----------------| | Volumes listed | `docker volume ls` | Volumes shown | | Volume mounted | `docker inspect <container>` | Mount point present | | Data persists | Delete and recreate container | Data still accessible | | Backup works | Extract backup archive | Files present |

Troubleshooting Scenarios

| Issue | Diagnosis | Resolution | |-------|-----------|------------| | Permission denied | Volume ownership mismatch | Fix permissions on host or use user flag | | Volume not mounting | Wrong path or volume name | Verify volume name and mount path | | Data lost after restart | No volume configured | Add volume mount to container | | Cannot remove volume | Volume in use by container | Stop and remove container first |

Best Practices

  • **Use named volumes for production:** Docker-managed, portable across hosts
  • **Use bind mounts for development:** Easy file editing on host
  • **Backup volumes regularly:** Critical for stateful applications
  • **Use volume drivers:** For network or cloud storage
  • **Clean up unused volumes:** Prevent disk space waste
  • **Document volume mount paths:** For team consistency

Security Considerations

  • **Volume permissions:** Ensure container user can write to volume
  • **Bind mount security:** Only mount trusted host directories
  • **Sensitive data:** Don't store secrets in volumes; use Docker Secrets
  • **Volume encryption:** Use encrypted volumes for sensitive data

Conclusion

Docker volumes and bind mounts provide persistent storage for stateful containers. By understanding the differences between named volumes, bind mounts, and tmpfs, and implementing proper backup procedures, you can run databases and other stateful applications reliably in Docker.

References

  • Docker Volumes: https://docs.docker.com/storage/volumes/
  • Bind Mounts: https://docs.docker.com/storage/bind-mounts/
  • Volume Plugins: https://docs.docker.com/engine/extend/plugins_volume/
  • Docker Storage: https://docs.docker.com/storage/
#stateful-containers#backup#data-management#persistent-storage#bind-mounts#volumes#Docker