20.1.1.5 Volume Mount Basics
A focused guide to Volume Mount Basics, connecting core concepts with practical Docker and container operations.
Volumes give containers access to persistent storage that exists independently of the container's lifecycle. By default, all data written inside a container goes into its writable layer, which is deleted when the container is removed. Volume mounts redirect writes to a storage location outside the container — either a Docker-managed directory (named volume) or a host filesystem path (bind mount) — so the data persists after the container is removed or replaced.
Why Volumes Are Necessary
Containers are ephemeral by design. When you remove a container, its writable layer is gone. For stateless applications (web servers, API handlers) this is fine. For stateful applications — databases, file storage, caches — the data must survive the container's lifecycle. Volumes solve this.
Additionally, volumes allow multiple containers to share the same data and allow data to be inspected and backed up from outside the container.
Types of Mounts
There are three types of mounts in Docker:
- Named volumes: Docker-managed storage under
/var/lib/docker/volumes/. Docker creates and manages the directory; you refer to it by name. - Bind mounts: A specific directory or file on the host filesystem is mounted into the container. You control the exact path.
- tmpfs mounts: In-memory storage that exists only while the container is running. Not persistent.
Named Volumes
Create and use a named volume with the -v flag:
docker run -d -v my_data:/app/data my_image
Format: -v <volume_name>:<container_path>
Docker creates the volume my_data if it does not exist. The container can write to /app/data, and the data is stored in Docker's volume directory. When the container is removed and a new one is started with the same volume, the data is still there:
docker rm my_container
docker run -d -v my_data:/app/data my_image
The new container finds the same data that the previous one wrote.
To create a volume explicitly before using it:
docker volume create my_data
To list all volumes:
docker volume ls
To inspect a volume and see where Docker stores it:
docker volume inspect my_data
Bind Mounts
A bind mount maps a specific host directory or file directly into the container:
docker run -d -v /home/user/config:/app/config nginx:latest
Format: -v <absolute_host_path>:<container_path>
Changes made inside the container at /app/config are immediately visible on the host at /home/user/config, and vice versa. The host directory must exist before running the container.
Bind mounts are commonly used for:
- Development workflows: Mount source code into a container so changes on the host are immediately reflected inside the running container without rebuilding the image.
- Configuration files: Provide runtime configuration from the host without baking it into the image.
- Log collection: Capture logs written by a container to a known host path for external log aggregation.
docker run -d -v $(pwd):/app my_dev_image
On Windows (PowerShell):
docker run -d -v ${PWD}:/app my_dev_image
Read-Only Mounts
To prevent the container from writing to a mounted path, add :ro:
docker run -d -v /host/config:/app/config:ro nginx:latest
The container can read files at /app/config but cannot write or delete them. This is useful for configuration files, secrets, and certificates that should not be modifiable from within the container.
The --mount Flag
The --mount flag is a more explicit alternative to -v with named fields:
docker run -d --mount type=volume,source=my_data,target=/app/data my_image
docker run -d --mount type=bind,source=/host/path,target=/app/config my_image
docker run -d --mount type=bind,source=/host/config,target=/app/config,readonly my_image
The --mount syntax is more verbose but less ambiguous than -v, which uses path format to determine whether the source is a volume name or a host path.
Named Volume vs. Bind Mount Comparison
| Named Volume | Bind Mount | |
|---|---|---|
| Storage location | Docker-managed directory | Specific host path |
| Created automatically | Yes | No (host path must exist) |
| Portable across hosts | Yes (data migrates with the volume) | No (relies on specific host path) |
| Good for | Production persistent data | Development, config injection |
| Accessible from host | Yes, but via Docker path | Yes, directly at the host path |
Sharing a Volume Between Containers
Multiple containers can mount the same volume simultaneously:
docker run -d --name writer -v shared_data:/data my_writer_image
docker run -d --name reader -v shared_data:/data my_reader_image
Both containers access the same data in shared_data. For applications that require coordination (databases, file locks), sharing volumes between containers requires the application to handle concurrent access.
Cleaning Up Volumes
Named volumes persist after containers are removed. To remove a specific volume:
docker volume rm my_data
To remove all volumes not currently used by a container:
docker volume prune
This is permanent — volume data is deleted and cannot be recovered.