How Docker Storage Works: Volumes vs Bind Mounts
Introduction
In this tutorial, you learn how Docker storage works and how to persist data using Docker Volumes and Bind Mounts. You also understand the key differences between these approaches and when to use each one in production. This helps you avoid data loss and design reliable containerized systems.
Prerequisites
- Target audience: Beginner system administrators
- Estimated time: ~30 minutes
- Operating system: Any OS with Docker support such as Ubuntu 22.04+, Debian 12+, CentOS Stream, or macOS with Docker Desktop
- Software: Docker 24.0.0 or later
- Permissions: User with access to Docker or sudo privileges
- Hardware: At least 2 GB RAM and 10 GB free disk space
- Network: Internet access to pull container images
- Assumed knowledge: Basic command line usage and understanding of containers
Step 1: Understanding How Docker Storage Works
Docker containers use a layered filesystem. Each container has a writable layer on top of read-only image layers.
What happens when a container writes data
- Docker stores image layers as read-only
- When you start a container, Docker adds a writable layer
- Any file changes happen only in this writable layer
Result
When you delete a container, all data in the writable layer is lost. This means container storage is ephemeral by default.
This behavior is useful for stateless applications but not for databases or persistent services.
Step 2: Creating and Using Docker Volumes
Docker Volumes are managed storage locations created and maintained by Docker.
Create a volume
Run the following command:
docker volume create my_volume
You should see the volume name returned.
Use a volume in a container
Run the following command:
docker run -d -v my_volume:/app/data --name volume_test busybox
Docker mounts the volume inside the container at /app/data.
Result
Data written to /app/data persists even if the container is removed.
Key characteristics of volumes
- Managed by Docker
- Stored in Docker internal directories such as
/var/lib/docker/volumes/ - Easy to back up and migrate
- Isolated from host filesystem structure
Use volumes for databases and production workloads.
Step 3: Creating and Using Bind Mounts
Bind mounts link a specific directory on the host to a directory inside the container.
Use a bind mount
Run the following command:
docker run -d -v /home/<YOUR_USERNAME>/data:/app/data --name bind_test busybox
Result
The container directly accesses the host directory. Any changes in the host directory are immediately visible inside the container.
Key characteristics of bind mounts
- Depend on host filesystem paths
- Allow direct file editing from the host
- No Docker-managed isolation
- More flexible but less portable
Bind mounts reflect changes immediately between host and container.
Step 4: Comparing Volumes and Bind Mounts
Understanding the differences helps you choose the right option.
Docker Volumes
- Managed by Docker
- Portable across environments
- Safer for production use
- Easier to back up
- Abstracted from host filesystem
Bind Mounts
- Managed by the host
- Tied to specific filesystem paths
- Useful for development
- Provide direct file access
- Less secure if misconfigured
Step 5: Choosing Between Volumes and Bind Mounts in Production
Use the following guidelines.
When to use Docker Volumes
- Running databases such as MySQL or PostgreSQL
- Storing application data that must persist
- Deploying production services
- Needing portability across servers
When to use Bind Mounts
- Local development environments
- Editing code or configuration files directly
- Debugging container behavior
- Temporary or test setups
Important: Bind mounts can expose sensitive host files to containers if misconfigured. Always verify paths and permissions.
Verification and Testing
Create a test container with a volume:
docker run -it -v my_volume:/data --name playground busybox
Inside the container, create a file:
echo test > /data/file.txt
Exit the container and remove it:
docker rm -f playground
Start a new container with the same volume:
docker run -it -v my_volume:/data --name playground busybox
Check the file:
cat /data/file.txt
Expected result: The file still exists, confirming data persistence.
Reverting Changes
To clean up resources, run the following commands:
docker rm -f playground volume_test bind_test
docker volume rm my_volume
docker system prune -f
Important: Removing volumes deletes all stored data permanently.
Troubleshooting
- Issue: Data disappears after container restart
Cause: No volume or bind mount used
Solution: Attach persistent storage using volumes or bind mounts - Issue: Permission denied errors
Cause: Host directory permissions mismatch
Solution: Adjust permissions usingchmodorchown - Issue: Volume not mounting correctly
Cause: Incorrect path or syntax
Solution: Verify mount format and paths
Conclusion and Next Steps
You learned how Docker storage works and how to persist data using volumes and bind mounts. You also understand when to use each approach in production. Next, explore Docker Compose to manage multi-container applications and define storage in a more structured way.