Docker Volumes and Persistent Storage
Introduction
By now, you have learned how to build and run Docker containers, and even create your own custom images. However, you've likely noticed that any data written inside a running container disappears once the container stops or is removed. This stateless nature is by design, but many real-world applications require data persistence: databases, logs, user uploads, and more.
Docker volumes are the primary mechanism Docker provides for persistent storage, decoupling your data from the lifecycle of containers. In this lesson, you will learn how to use Docker volumes to persist, share, and manage data across containers.
Why Persistent Storage Matters
Containers are ephemeral—when they're deleted, their filesystem changes are lost. Consider these scenarios:
- A database running in a container loses all its data when the container is removed.
- Uploaded files to a web app are gone after the app restarts.
- Application logs aren’t available for troubleshooting after a crash.
Persistent storage solves these problems by storing data outside the container's writable layer.
Docker Storage Options
Docker provides multiple ways to manage persistent data:
- Volumes (recommended): Managed by Docker, stored outside container filesystem.
- Bind mounts: Mount specific host directories/files into the container.
- tmpfs mounts: Store data in host memory, not persisted after restart (not covered in detail here).
We will focus primarily on volumes, but will also introduce bind mounts for completeness.
Understanding Docker Volumes
What is a Docker Volume?
A volume is a directory (or file) stored outside the container’s Union File System, managed by Docker. Volumes are independent of the container lifecycle—deleting a container does not delete its volumes.
Key characteristics:
- Can be shared and reused among containers.
- Easier to back up or migrate than bind mounts.
- Managed entirely by Docker.
Creating and Listing Volumes
Create a volume:
docker volume create mydata
List all volumes:
docker volume ls
Inspect a volume:
docker volume inspect mydata
Using Volumes in Containers
Mount a volume into a container using the -v or --mount flag.
Using -v (short syntax):
docker run -d \
--name my_nginx \
-v mydata:/usr/share/nginx/html \
nginx
mydatais the name of the volume./usr/share/nginx/htmlis the path inside the container.
Using --mount (long syntax):
docker run -d \
--name my_nginx \
--mount type=volume,source=mydata,target=/usr/share/nginx/html \
nginx
Both methods achieve the same result. The long syntax is more explicit and flexible.
Bind Mounts vs. Volumes
A bind mount links a specific file or directory on the host to the container.
docker run -d \
--name my_nginx \
-v /home/user/website:/usr/share/nginx/html \
nginx
Differences:
| Aspect | Volume | Bind Mount |
|---|---|---|
| Managed by Docker | Yes | No |
| Storage location | Docker-managed directory | Any host directory/file |
| Backup/migration | Easy (via Docker CLI) | Manual |
| Use case | Application data, databases | Source code, configs |
Use volumes for application data; use bind mounts mainly for development or config injection.
Common Use Cases for Docker Volumes
- Databases: Persisting database files (
/var/lib/mysql,/var/lib/postgresql/data). - Application uploads: User-generated files in web apps.
- Logs: Retaining application/service logs outside containers.
- Sharing data between containers: E.g., sharing a socket file.
Example: Persisting MySQL Data
docker volume create mysql_data
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-v mysql_data:/var/lib/mysql \
mysql:8
- MySQL data files are now stored in the volume
mysql_data. - Stopping or removing the container keeps your data safe.
Removing Volumes
Volumes are not deleted when you remove a container by default.
Delete a volume explicitly:
docker volume rm mydata
Or remove all unused volumes:
docker volume prune
Sharing Volumes Between Containers
Multiple containers can access the same volume. This is useful for:
- Web/app and worker containers sharing uploaded files.
- Log aggregation.
Example:
docker run -d --name web -v shared_data:/app/data mywebapp
docker run -d --name worker -v shared_data:/app/data myworker
Backing Up and Restoring Volumes
Backup:
docker run --rm \
-v mydata:/data \
-v $(pwd):/backup \
alpine \
tar czf /backup/mydata.tar.gz -C /data .
Restore:
docker run --rm \
-v mydata:/data \
-v $(pwd):/backup \
alpine \
tar xzf /backup/mydata.tar.gz -C /data
Common Mistakes and Pitfalls
- Confusing Volumes with Bind Mounts: Bind mounts reference host paths; volumes are managed by Docker.
- Accidentally Deleting Volumes:
docker volume rmordocker volume pruneis irreversible. - Mounting Volumes Over Existing Data: Data in the container at the mount point is hidden by the volume.
- Permissions Issues: The container user may not have write permissions to the volume, especially when using custom images.
Summary
- Volumes provide persistent, Docker-managed storage decoupled from the container lifecycle.
- Use volumes for databases, uploads, logs, and shared data.
- Volumes are safer and easier to manage than bind mounts for most persistent storage needs.
- Always check mount points and permissions to avoid data loss or access issues.
Quiz
-
What happens to data written inside a container if you do not use a volume or bind mount?
Answer: The data is lost when the container is removed, as it is stored in the container's ephemeral writable layer.
-
How can you list all Docker volumes on your system?
Answer: By running
docker volume ls. -
Which is the recommended method for persisting database files in Docker: volumes or bind mounts?
Answer: Volumes are recommended for persisting database files.
-
What is a common mistake when mounting a volume into a container at a path that already contains data?
Answer: The existing data at that path inside the container becomes hidden by the mounted volume.
-
True or False: Removing a container will always delete its associated volumes.
Answer: False. Volumes persist even after the container is removed unless they are explicitly deleted.