Comprehensive guidance for managing persistent data in Docker.
When to Use
ALWAYS use this skill when the user mentions:
- "docker volume", "data volume", "data persistence"
- "bind mount", "tmpfs"
- "how to save container data", "data not lost"
- "how to persist database containers"
- "backup and restore", "storage driver"
Storage Type Comparison
| Type | Persistence | Performance | Use Case |
|---|---|---|---|
| Volume | ✅ (managed by Docker) | High (native) | Production databases, shared data |
| Bind Mount | ✅ (host filesystem) | High | Development (live code sync), config files |
| Tmpfs | ❌ (memory only) | Highest | Secrets, temp files, sensitive data |
Visual Comparison
Volume: Bind Mount: Tmpfs:
Container Container Container
│ │ │
Docker-managed /host/path Memory only
/var/lib/docker/volumes/ ↕ (no disk)
↕ Container sees: ↕
Container sees: /container/path Container sees:
/data = host files /tmp (in RAM)
Volume Management
# Create & inspect
docker volume create mydata
docker volume ls
docker volume inspect mydata
# Use in container
docker run -v mydata:/var/lib/mysql mysql:8
docker run --mount source=mydata,target=/var/lib/mysql mysql:8 # explicit syntax (recommended)
# Cleanup
docker volume prune # Remove unused volumes
docker volume rm mydata # Remove specific volume
Named vs Anonymous Volumes
-v mydata:/data → Named volume (mydata) — survives container removal ✅
-v /data → Anonymous volume — hard to identify later ❌
Bind Mount
# Read-write bind mount
docker run -v $(pwd)/app:/app nginx
# Read-only (protect host files)
docker run -v $(pwd)/config:/etc/nginx:ro nginx
# Explicit syntax
docker run --mount type=bind,source=$(pwd)/app,target=/app nginx
Tmpfs (Memory)
# Ephemeral data, never touches disk
docker run --tmpfs /tmp:rw,noexec,nosuid,size=64m nginx
docker run --mount type=tmpfs,destination=/tmp,tmpfs-size=64m nginx
Database Persistence Patterns
PostgreSQL
docker volume create pgdata
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:16-alpine
MySQL
docker volume create mysqldata
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-v mysqldata:/var/lib/mysql \
-v $(pwd)/my.cnf:/etc/mysql/conf.d/my.cnf:ro \
-p 3306:3306 \
mysql:8.4
Redis (Persistence)
docker volume create redisdata
docker run -d \
--name redis \
-v redisdata:/data \
-p 6379:6379 \
redis:7-alpine redis-server --appendonly yes
Backup & Restore
# Backup (using a temporary container)
docker run --rm \
-v mysqldata:/source \
-v $(pwd):/backup \
alpine tar czf /backup/mysqldata-backup.tar.gz -C /source .
# Restore
docker run --rm \
-v mysqldata:/target \
-v $(pwd):/backup \
alpine tar xzf /backup/mysqldata-backup.tar.gz -C /target
Storage Drivers
| Driver | Status | Notes |
|---|---|---|
| overlay2 | ✅ Default | Best for most use cases; copy-on-write |
| devicemapper | Deprecated | - |
| aufs | Deprecated | - |
| btrfs/zfs | Niche | Use if filesystem matches |
docker info | grep "Storage Driver" # Check current
Workflow — Recommended Configuration Process
Step 1: Determine storage type: persistent data → Volume; development hot reload → Bind Mount; temporary cache → tmpfs
Step 2: Create Volume: docker volume create db_data
Step 3: Mount to container: docker run -v db_data:/var/lib/mysql mysql
Step 4: Verify: docker volume inspect db_data + docker exec mysql ls /var/lib/mysql
Step 5: Backup: docker run --rm -v db_data:/source -v $(pwd):/backup alpine tar czf /backup/db.tar.gz -C /source .
Gotchas — Common Pitfalls
- Anonymous volumes accumulate: Every
-v /data(no name) creates a new anonymous volume. → Recovery:docker volume prunecleans all unused; use named volumes:-v mydata:/data. - Bind mount paths: Must be absolute. → Recovery:
-v $(pwd)/app:/appfor docker run;-v ./app:/appworks in Compose only. - Permission issues with bind mounts: Container UID != host UID → permission denied. → Recovery:
--user $(id -u):$(id -g)orRUN chown 1000:1000 /datain Dockerfile entrypoint. - Data loss on container removal: Without
-v, data is lost when container is removed.--rmflag even worse. → Recovery: Always use named volumes:docker run -v db_data:/var/lib/mysql. - macOS bind mount performance: Bind mounts on Docker Desktop Mac are slow. → Recovery: Use
:cachedor:delegatedmount options, or named volumes for better I/O.
Boundary — Capability Boundaries (Applicable and Non-Applicable Scenarios)
| Category | Scenario | Description |
|---|---|---|
| ✅ Can do | Data persistence configuration (Volume/Bind Mount/tmpfs) | Creation, mounting, and management of the three storage types |
| ✅ Can do | Backup and restore | tar + --volumes-from Backup and restore |
| ✅ Can do | Storage driver selection | overlay2/btrfs/zfs comparison |
| ⚠️ Conditional | NFS/cloud storage Volume drivers | Requires installation of the corresponding driver plugin |
| ⚠️ Conditional | Bind Mount performance on macOS | Use :cached/:delegated or named Volume |
| ❌ Out of scope | K8s PersistentVolume/PVC | Use docker-production + K8s documentation |
| ❌ Out of scope | Distributed file systems (Ceph/GlusterFS) | System administrator domain |
| ❌ Out of scope | Database performance optimization | DBA professional domain |
When NOT to Use This Skill
| ❌ Skip | ✅ Use Instead |
|---|---|
| Running containers (no data concerns) | docker-run |
| Multi-container orchestration | docker-compose |
| Kubernetes Storage (PV/PVC) | K8s documentation |
| Docker basics | docker-basics |
Security & Stability
- Use
:rofor config files that containers should not modify. - Never bind mount Docker socket (
/var/run/docker.sock) without understanding the security implications. - Backup volumes regularly, especially database volumes.
- No executable scripts bundled. Guidance only.
📚 Official Documentation References
| Documentation | Address |
|---|---|
| Docker Storage | https://docs.docker.com/storage/ |
| Volumes | https://docs.docker.com/storage/volumes/ |
| Bind Mounts | https://docs.docker.com/storage/bind-mounts/ |
| tmpfs | https://docs.docker.com/storage/tmpfs/ |
| Storage Drivers | https://docs.docker.com/storage/storagedriver/ |
| docker volume command | https://docs.docker.com/reference/cli/docker/volume/ |
🧭 Docker Skills Journey
📍 You are here:
docker-storage— Data Persistence
← Previous: docker-run / docker-networking
→ Next: docker-compose / docker-security
FAQ
Q1: How do I quickly get started with this skill? A: Refer to the Quick Start section above and follow the steps.
Q2: What should I do if I encounter version incompatibility issues? A: Check dependency versions, use a lock file to pin them, and refer to the Common Pitfalls section.
Q3: How do I use it in a production environment? A: Refer to the Best Practices section, ensure the configuration is correct, and set up monitoring and logging.
Q4: How can performance be optimized? A: Refer to the performance optimization documentation and use techniques such as caching and indexing.
Q5: How can I contribute or provide feedback? A: Submit an Issue or Pull Request in the GitHub repository.
Q6: Is Chinese supported? A: Chinese documentation and Chinese comments are supported; see the Domestic Adaptation section for details.