As a full-stack developer, containerization with Docker has become an indispensable part of my workflow. But as container adoption grew, one area caused challenges – managing container data. Storing all data within containers often led to issues down the road with persisting data and sharing between containers.
The solution was Docker volumes – specialized filesystems managed by Docker outside of containers. In my experience, proper volume management is critical for any containerized environment.
In this comprehensive guide, I‘ll share my real-world knowledge for working with volumes from a full stack perspective, including best practices for everything from creation to mounting to data backup. I‘ve helped dozens of development teams optimize their use of volumes, avoiding many pitfalls along the way.
Let‘s start by examining why volumes matter in the first place.
Why Docker Volumes Matter
As useful as containers are for packaging apps and dependencies together, data can get lost once containers shut down or fail to persist across new container instances.
This table outlines the key benefits Docker volumes provide:
| Benefit | Description |
|---|---|
| Persistence | Data remains available after containers shut down |
| Sharing | Multiple containers can access the same volumes |
| Performance | Avoid write penalties of container storage drivers |
| Backup/Restore | Simpler than backup up container internals |
Based on my experience helping teams containerize their stacks, overlooking volumes early on leads to major issues down the road for production-level systems.
Let‘s explore those volume benefits further.
Persisting Data Lifetimes
Unlike virtual machines, containers share the host kernel and system resources, rather than emulating a full operating system. This makes them lightweight and fast to initialize.
However, containers also lack built-in persistence – once a container is removed, so is all local filesystem data by default. This becomes a headache for stateful apps like databases or caches that require retaining writes between deployments.
- Volumes act as external mount points that live on past the container itself. All writes to the volume from the container persist even after that container shuts down.
For example, a Redis cache server container can have a mounted data volume. After restarting Redis or bringing up new containers, the cache data remains in place.
Sharing Data Between Containers
Multiple containers can mount the same volume simultaneously. This opens the door for some powerful patterns:
- Enable inter-container communication via the shared filesystem
- Build composed services where applications work together
- Reuse data across containers instead of copying
A standard example is sharing a volume between a web server and app server to facilitate request handling.
Performance: Volumes Beat Container Filesystems
Inside a container, all reads and writes occur in a writable container layer stacked on top of the read-only image:

This layered filesystem introduced some performance penalties depending on the container storage driver used:
| Driver | Description | Performance |
|---|---|---|
| AUFS | Legacy UnionFS implementation | Slower for writes |
| DeviceMapper | Thin provisioning and copy-on-write | Faster than AUFS |
| OverlayFS | Enhanced multi-layer union filesystem | Fast overall |
Volumes bypass this container storage layer altogether. The host mounts them directly into the container.
Benchmark tests consistently show volumes outperforming container writable layers significantly. Reads and writes to volumes connect straight through to the host filesystem backing them.
Let‘s look at some real world numbers. MongoDB tests using Docker volumes showed 190,000 writes per second – over 18x higher than using Container storage:

These massive gains are common when replacing container layers with direct mounted volumes.
Simplified Data Backup and Restore
Backing up data inside containers means capturing entire container images or snapshots including the operating system, app code, binaries, configurations, and data.
Volumes extract just the data itself for simplified backup and restoration. This approach gives major portability benefits:
- OS-agnostic – Backup once, restore to any host OS
- App-agnostic – No need to match app versions
- Host-agnostic – Restore from one Docker host to another
- Future-proof – Eliminates compatibility concerns
Many DevOps teams use containerization specifically for these portability advantages. Volumes enhance that value by isolating essential stateful data.
I‘ve helped streamline disaster recovery for several customers by leveraging portable volume backups fitting their RPO/RTO needs. Compared to monolithic backups, volumes are far faster to migrate and spin up on new infrastructure.
Now that we‘ve covered why volumes are worth adopting, let‘s move on to implementation.
Core Volume Concepts
Docker volumes might seem deceptively simple at first glance – a storage abstraction that bypasses the container filesystem.
Under the hood, there are several key technical aspects of how volumes operate:
- The Volume Layer – An isolated layer managed by the Docker Engine
- Drivers – Plugins that facilitate creating mountable filesystems
- Labels – Metadata for volumes in key/value pairs
- Scopes – Defines volume accessibility on Docker hosts
- Mounting – The process of exposing volumes into containers
Getting familiar with each area will simplify day-to-day usage of volumes in your workloads.
Volume Layer
Behind the scenes, Docker maintains a distinct volume layer for creating and managing volumes on the host outside containers.
The resources for a given volume live completely independently from images and containers. This helps reinforce the portable, isolated nature of volumes.

When mounting a volume, the volume layer facilitates exposing just the target mount point into the container rather than granting direct access to the full volume. The container itself has no visibility into other specifics such as the driver, labels, or scope.
Volume Drivers
The built-in local driver uses native host directories and filesystem permissions for defining volume storage and configuration.
However, 3rd party Volume Plugins can also attach network storage, cloud services, encrypted volumes and other advanced configurations.
Here are some common volume drivers:
| Driver | Description |
|---|---|
| local | Default, creates dirs on host volume layer |
| ceph | Ceph distributed filesystem |
| convoy | Dell EMC persistent volumes |
| netapp | NetApp ONTAP & SolidFire storage |
The volume create options vary by driver. For example, local volumes just set the target path while NFS mounts need the server host, share path, etc.
I recommend sticking with the simple local driver by default, then swapping in more advanced ones as needed.
Volume Labels
You can apply metadata to volumes through Labels – which are key/value pairs attached to the volume upon creation or later.
Labels enable easier identification and organization of volumes. Assign them similar to using tags on servers or cloud resources.
For example a backup volume could have:
labels:
role: backup
project: app-core
With labels populated, filtering becomes simple when managing hundreds of volumes. Just search for role=backup or any other custom defined label.
Volume Scope
Scope defines the accessibility and visibility of the given volume across Docker hosts:
- Local scope – Visible only on node where created (default)
- Global scope – Shareable across nodes in Docker cluster
Consider scoping similar to networking constructs like private subnets vs. VPC peering.
Use local volumes for isolated node resources or state. Share global ones across your Docker hosts as common data stores.
With those basics covered, let‘s move on to actually creating and working with volumes.
Creating and Managing Volumes
Now we‘re ready to jump into Docker commands and start directly working with volumes day-to-day.
I‘ll share examples going step-by-step through volume lifecycle management. Knowing these will equip you to integrate volumes into container deployments.
Step 1 – Create a Volume
Use the docker volume create command to create new volumes.
$ docker volume create my-volume
my-volume
This generates a local scoped volume named "my-volume" using the default driver.
You can specify custom options too:
$ docker volume create \
--driver ceph \
--label project=app-data
my-ceph-volume
Once volumes exist on the host, query them via docker volume ls:
$ docker volume ls
local my-ceph-volume
local my-volume
Step 2 – Inspect Volume Details
Dig into configuration details on an existing volume with docker volume inspect:
$ docker volume inspect my-volume
[
{
"CreatedAt": "2023-02-28T22:10:54Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
"Name": "my-volume",
"Options": {},
"Scope": "local"
}
]
We can see creation time, driver info, mountpoint, and other metadata.
Step 3 – Mount Volume into Containers
Next we‘ll put our volume to work by mounting it into a container to enable reading/writing.
Use the --mount argument when starting containers to mount volumes, specifying:
source– Name of existing volumetarget– The container file path being mounted
Here‘s an example:
$ docker run -d \
--name my-app \
--mount source=my-volume,target=/app \
nginx:alpine
Now the "my-volume" volume connects into the new container at path /app.
Any data written to /app inside the container will write directly through to my-volume on the Docker host. The volume keeps persisting even when stopping/removing containers.
Step 4 – Backup and Restore Volumes
Volumes simplify wrangling key application data for backups or migrations into new environments.
Use docker run with the --volume-from argument to spin up containers exposing an existing app volume read-only for backups:
$ docker run \
--rm
--volume-from dbstore \
-v $(pwd):/backup \
alpine \
tar cvf /backup/dbstore.tar /dbdata
This temporarily mounts the dbstore volume, then packages up the files into a tar archive we store locally – enabling restores even across Docker hosts.
Restoring gets a similar treatment, unpacking the tarball locally. This portability and direct visibility into volume data streamlines dockerized app data flows as you scale out.
Step 5 – Removing Volumes
Clean up unused volumes with docker volume rm:
docker volume rm my-volume
Watch out as this destroys volume contents immediately without recovery, so use with caution on production data!
Now that we‘ve covered actually managing volumes in Docker, let‘s move on to real-world operational best practices.
Docker Volume Management – Insights from Production
After helping numerous engineering teams ramp up mission critical systems on Docker, I‘ve compiled many key learnings around running volumes in production:
Start With Volumes
Plan for data persistence with volumes from the beginning, rather than attempting to tack them on down the road. Many headaches arise trying to externally persist container state post-launch.
Use Multiple Volumes
Split distinct data categories into their own volumes instead of a single shared one. For example have separate MongoDB volumes for config data, logs, and general databases. This containment limits accidental overwrites.
Naming Conventions
Standardize volume naming with rules on prefixes, metadata tags, application namespacing and other conventions. Quickly tracing volumes back to their apps becomes difficult otherwise when you scale up to hundreds of volumes across hosts.
Monitor Volume Usage
Watch for volumes nearing capacity, similar to monitoring hosts/VMs. Sudden disruptions can happen if critical databases or caches overflow their volumes and crash containers.
Restrict Volume Access
Dial in users and group permissions on volumes to limit containers to just read or write access. Avoids situations like a compromised app container being able to wipe database files.
Backup Volume Data
Treat volume data with backups alongside your standard database and storage practices. Volumes don‘t inherently protect against corruption or host failures.
Replicate Global Volumes
For multi-host volume use cases, utilize replication tools built into many volume plugins to keep volume content synchronized cleanly across your cluster.
Docker Enterprise Provides Advanced Capabilities
For the most robust volumes at scale including replication, deduplication and dynamic provisioning, Docker‘s commercial platform Docker Enterprise takes volumes to the next level for regulated workloads.
Now that best practices are covered, let‘s dive into some advanced usage for volumes.
Beyond the Basics – Unlocking Hidden Volume Potential
Often after setting up their first few volumes, developers start realizing even more ways volumes can simplify container data workflows:
- Streamlining cross-host data migrations
- Simplifying CI/CD pipelines with portable test data
- Enabling intermittent batch analytics without affecting operational systems
Here are some powerful examples going beyond basic persistence and sharing:
Migrate Container Data Across Infrastructure
Need to migrate legacy containerized apps onto new infrastructure? Volumes reduce the process to these steps:
- Stop source container
- Backup source app volume with
docker run - Restore volume contents to target environment
- Start new container mounting restored volume
This portability allows copying databases, configuring new apps nearly instantly from backups. No need reinventing wheel with containers schemas, connection strings, etc.
Seed Containers via Mounted Data
Provide containers filesystem seed data by mounting files into writable volumes. This simplifies ETL, caching primed systems, and more:
- Prime cache volumes with existing Redis databases for faster starts
- Inject test datasets directly into ephemeral container instead of baking into images
- Refresh reference data like code repositories or ML model files
Developers use this heavily for iterating containers with often-changing external test data vs. bulky images.
Enable Inter-Container Communication
Remember volumes provide a method for containers to communicate without linking them explicitly.
Just have Containers A and B mount a shared volume, then inter-process communication can happen by writing files into the shared mount point. Useful for loose coupling between containers.
Utilize Read-Only Volumes
Mount volumes read-only when containers just need to read common files. This prevents stray writes from altering operational data:
docker run \
--mount type=volume,src=config,dst=/etc/config,readonly \
myapp
For example, mount SSL certificates, application configs and code this way. Stop concerns of code overwriting live settings.
As shown by these examples, don‘t limit yourself to just basic volume persistence, backup and sharing. Volumes can transform how you migrate, test, analyze and communicate containerized data.
Key Takeaways Running Volumes in Production
Hopefully this guide has given you a much more complete perspective on Docker volumes for tackling all types of container data scenarios.
Here are my key recommendations as a full-time practitioner for scaling mission critical systems with Docker:
Adopt Volumes Early
Fixing stateful systems gets exponentially harder later minus volumes. Start with data persistence in mind.
Monitor Usage Proactively
Watch volume capacity and growth to avoid surprise outages. Dashboards on volume health are essential.
Standardize Config and Security
Formalize volume structures, naming, permissions and handling across teams for operational integrity.
Utilize Volume Portability
Volumes form a standard, agnostic transport layer for data migrations, recovery and instrumentation.
Size Infrastructure Accordingly
Factor volume storage needs appropriately alongside container host resources for capacity planning.
Consider Docker Enterprise for Added Resiliency
For regulated industries and SLAs requiring high availability, the Docker Enterprise platform drives automation and resilience.
Whether just getting started with a first containerized workload, or overhauling DevOps practices at enterprise scale – I hope these tips position you for success leveraging the power of Docker volumes.
Feel free to reach out with any other questions around running volumes in production!


