Named Volumes
Learn Docker named volumes, creating, using, inspecting and sharing named volumes between containers for persistent data storage that survives container restarts and deletion.
A container is easy to replace. That is one of Docker’s biggest strengths. But the same feature creates a serious problem the moment your application stores real data. If you remove a container that has been writing into its own filesystem, that data disappears with it. Named volumes solve this by moving important data outside the container lifecycle.
Named volumes are the standard Docker answer for persistent application storage. They are simple to use, portable across containers, and managed directly by Docker.
What Are Named Volumes?
A named volume is a Docker-managed storage location with a name you choose, such as postgres-data or uploads. Instead of mounting a host path manually, you tell Docker to attach that volume name to a container path.
docker run -d --name db -v postgres-data:/var/lib/postgresql/data postgres:16
In this example:
postgres-datais the named volume/var/lib/postgresql/datais the path inside the container- Docker creates the volume automatically if it does not already exist
Why named volumes exist
Named volumes are useful because they separate data lifecycle from container lifecycle.
A container may be stopped, replaced, recreated, or upgraded. The volume remains until you explicitly remove it.
That makes named volumes ideal for:
- databases
- uploaded user files
- CMS content
- application-generated persistent data
- any service that must keep state between container restarts
When to Use Named Volumes
Named volumes are usually the right choice when:
- the data should survive container removal
- you do not need to edit the files directly from the host every day
- you want Docker to manage the storage location
- multiple containers need access to the same persistent dataset
- you want a more portable solution than a host-specific path
A beginner shortcut is this:
- Use named volumes for application data
- Use bind mounts for local source code and host-managed files
Creating Volumes with docker volume create
You can let Docker create a volume automatically on first use, but it is often helpful to create it explicitly.
docker volume create myvolume
Docker responds with the volume name:
myvolume
Now it exists independently of any container.
Why create volumes explicitly?
Explicit creation helps because you can:
- choose meaningful names
- inspect the volume before use
- create infrastructure in a predictable order
- avoid accidental anonymous volumes
For example:
docker volume create postgres-data
docker volume create app-uploads
docker volume create shared-logs
Descriptive names make cleanup and troubleshooting much easier later.
Mounting Volumes with -v
The shortest syntax is -v.
docker run -d \
--name app \
-v myvolume:/app/data \
my-image
The format is:
-v volume-name:/path/in/container
Docker checks whether myvolume exists:
- if yes, it mounts it
- if no, Docker creates it and then mounts it
Example: persistent application data
docker run -d \
--name notes-app \
-p 3000:3000 \
-v notes-data:/app/data \
my-notes-image
If the app writes files into /app/data, those files stay in the volume even if you remove the container.
Mounting Volumes with --mount
The --mount syntax is longer but clearer and more explicit.
docker run -d \
--name app \
--mount type=volume,source=myvolume,target=/app/data \
my-image
This says the same thing as the -v example, but the fields are named:
type=volumesource=myvolumetarget=/app/data
Why many teams prefer --mount
--mount is easier to read in scripts and documentation, especially once you add more options. With -v, beginners sometimes mix up volume names and host paths. --mount makes the intent explicit.
Understanding docker run -v myvolume:/app/data
This command is worth pausing on because it is one of the most important volume patterns in Docker.
docker run -v myvolume:/app/data my-image
What happens?
- Docker looks for a volume named
myvolume - If it does not exist, Docker creates it
- Docker mounts it at
/app/datainside the container - Any file the container writes under
/app/datais stored in the volume - The data remains after the container stops or is deleted
The key insight is that the container path acts like an attachment point. The real data is not tied to the container filesystem anymore.
Persistence Across Container Removal
Named volumes become most valuable when you replace containers.
# First container writes data
docker run -d --name db -v pgdata:/var/lib/postgresql/data postgres:16
# Later, remove the container
docker rm -f db
# Recreate a fresh container with the same volume
docker run -d --name db -v pgdata:/var/lib/postgresql/data postgres:16
The database files remain because they live in pgdata, not in the removed container.
This pattern is extremely common in upgrades:
- stop an old container
- start a new container version
- mount the same named volume
- keep the existing data
Sharing a Volume Between Multiple Containers
One named volume can be mounted into more than one container.
docker volume create shared-data
docker run -d \
--name writer \
-v shared-data:/data \
alpine sh -c "while true; do date >> /data/log.txt; sleep 5; done"
docker run -d \
--name reader \
-v shared-data:/logs:ro \
alpine sh -c "tail -f /logs/log.txt"
Here:
- the
writercontainer writes to the volume - the
readercontainer mounts the same volume read-only and watches the file
Safe sharing patterns
The safest design is usually:
- one writer
- one or more readers
If multiple containers write to the same files without coordination, data corruption can happen. The volume itself does not provide application-level locking. Your application still needs to handle concurrency correctly.
Inspecting Volumes with docker volume ls
To list all volumes on the machine:
docker volume ls
Example output:
DRIVER VOLUME NAME
local myvolume
local pgdata
local app-uploads
This is useful for:
- checking whether a volume exists
- spotting old unused volumes
- verifying naming conventions
- seeing which driver a volume uses
If your machine has many projects, docker volume ls becomes a routine cleanup and troubleshooting command.
Inspecting Details with docker volume inspect
To see metadata about one volume:
docker volume inspect myvolume
You usually get JSON output like:
[
{
"CreatedAt": "2026-07-12T12:00:00Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/myvolume/_data",
"Name": "myvolume",
"Options": {},
"Scope": "local"
}
]
Important fields
- Name: the volume name
- Driver: how Docker manages the volume
- Mountpoint: where the data is stored on the host
- Scope: usually
localfor normal single-host use
This is the command you run when you want to answer, “Where is this volume actually stored?”
Where Docker Stores Volume Data on the Host
On Linux with the local driver, Docker often stores named volume data under a path like:
/var/lib/docker/volumes/<volume-name>/_data
For example:
/var/lib/docker/volumes/myvolume/_data
Important platform note
On Docker Desktop for macOS and Windows, Docker usually runs inside a lightweight VM. That means the volume data is not as directly accessible in the same way as on a native Linux host. You should think of Docker as managing the location for you rather than relying on browsing the files manually.
That is one reason named volumes are nice: your workflow does not depend heavily on knowing the exact host path.
Volume Drivers
The default volume driver is local, and that is what most beginners use.
docker volume create myvolume
This uses the local driver unless you specify something else.
Local driver
The local driver stores volume data on the same Docker host. It is perfect for:
- local development
- single-server deployments
- most beginner and intermediate use cases
Network and remote drivers
Docker also supports other drivers, depending on your environment and plugins. Examples include:
- NFS-backed storage
- cloud provider integrations
- distributed storage systems
A conceptual example might look like:
docker volume create \
--driver local \
--opt type=nfs \
--opt o=addr=192.168.1.10,rw \
--opt device=:/exports/appdata \
nfs-data
In production environments, remote or network-backed drivers are useful when data must outlive a single machine or be shared across hosts.
For most learners, though, focus on the local driver first. It teaches the core idea clearly.
Removing Volumes with docker volume rm
To delete a specific volume:
docker volume rm myvolume
Docker removes the volume only if it is not in use by a container.
Why removal can fail
If a container still references the volume, Docker refuses:
Error response from daemon: remove myvolume: volume is in use
That safety check helps prevent accidental data loss.
Before removing a volume, make sure:
- the container using it is stopped or removed
- you have backed up any important data
- no other service depends on it
Cleaning Up with docker volume prune
Over time, volumes accumulate. Some are still important. Others are leftovers from experiments, deleted containers, or old Compose projects.
To remove all unused volumes:
docker volume prune
Docker asks for confirmation. To skip the prompt:
docker volume prune -f
Why prune carefully
An “unused” volume may still contain important data. Docker only knows whether a volume is attached to a container, not whether you care about the contents. Always inspect before pruning in environments that matter.
Named Volumes vs Bind Mounts
Named volumes and bind mounts both store data outside the container, but they serve different needs.
| Topic | Named Volume | Bind Mount |
|---|---|---|
| Managed by | Docker | You |
| Host path knowledge | Usually not needed | Required |
| Portability | Higher | Lower |
| Best for | Persistent app data | Local development and host file injection |
| Safety from accidental host edits | Better | Lower |
If you are storing database files, named volumes are usually the right first choice.
Practical Use Cases
Database persistence
docker run -d --name postgres -v pgdata:/var/lib/postgresql/data postgres:16
User uploads directory
docker run -d --name app -v uploads:/app/uploads my-app
Shared logs between containers
docker run -d --name app -v shared-logs:/var/log/app my-app
docker run -d --name collector -v shared-logs:/logs:ro alpine tail -f /logs/app.log
These examples all share one theme: the data should persist even if the container changes.
Best Practices
Use descriptive names
Prefer postgres-data over data1. Clear names reduce mistakes.
Back up important volumes
A named volume is persistent, but it is not magical. You can still delete it. Persistence is not the same as backup.
Avoid manual host edits unless necessary
Let Docker and your containers manage the data unless you have a specific reason to intervene.
Be careful with shared writes
A volume does not protect you from concurrent write issues.
Clean up old volumes regularly
Unused volumes quietly consume disk space. Periodic inspection and pruning keep your host healthy.
Common Beginner Mistakes
-
Assuming deleting a container deletes the volume It does not. Named volumes persist independently.
-
Using bind mounts for database data without a reason This often adds host-path complexity you do not need.
-
Removing a volume before checking its contents That can destroy important application state.
-
Forgetting that Docker can auto-create volumes This can lead to accidental anonymous or unexpected volumes if you mistype a name.
-
Expecting a volume to solve application-level file locking It only provides shared storage, not concurrency control.
Final Takeaway
Named volumes are the default Docker answer for persistent container data. They are simple, reliable, and designed for the exact problem containers create: disposable compute with durable storage. Learn the docker volume create, docker volume ls, docker volume inspect, and docker volume rm commands well, and you will be comfortable managing stateful Docker workloads.
Knowledge Check
Question 1: Persistence
Why are named volumes commonly used with databases in Docker?
Question 2: Volume Inspection
Which command shows details such as the driver and mountpoint of a Docker volume?
Question 3: Shared Use
What is usually the safest pattern when multiple containers access the same named volume?