Posted on 29 Jul 2026
This is the fifth article of the Getting Started with Docker series. In the previous article we connected containers over a private network. Now we need to address another fundamental question: what happens to your data when a container is stopped or replaced?
By default, a container’s filesystem is ephemeral — everything written inside it disappears when the container is removed. This is fine for stateless services like a web server, but it is a problem as soon as you have anything that needs to survive: logs, configuration, user data, database files.
Docker solves this with volumes.
One of Docker’s main benefits is that upgrading an application is as simple as replacing the old container with a new one. But if your data is stored inside the container, replacing it means losing the data.
The solution is to separate the application binaries from the data. Store the binaries in the image and the data in a volume that lives outside the container. When you replace the container, the volume stays where it is and the new container picks it up.
Docker provides three options for persisting data from a container to the host filesystem.
Volumes are managed entirely by Docker. They are stored in a directory on the host that Docker controls (typically /var/lib/docker/volumes/ on Linux) and you interact with them through Docker CLI commands — not by poking around the filesystem directly.
Volumes are the recommended way to persist data in Docker. From the official documentation, some of the reasons:
Bind mounts map a specific directory or file on the host filesystem into the container. Unlike volumes, bind mounts are not managed by Docker — any process on the host can read and write them.
Bind mounts are ideal when:
We already used a bind mount in the first article: -v $(pwd)/index.html:/usr/share/nginx/html/index.html:ro.
Tmpfs mounts store data in the host’s memory, not on disk. The data is never written to disk and disappears when the container stops. They are useful for sensitive data (secrets, tokens) that should never touch disk, or for temporary scratch space that requires very fast I/O.
Tmpfs mounts are only available on Linux hosts.
--mount SyntaxDocker has two ways to attach storage to a container: the older -v flag and the newer --mount flag. The --mount syntax is more explicit and is the one recommended by the official documentation today.
Comparison:
# Old syntax (-v)
docker run -v my-volume:/app/data nginx:alpine
# New syntax (--mount) — equivalent
docker run --mount type=volume,source=my-volume,target=/app/data nginx:alpine
The --mount form accepts key-value pairs:
type — volume, bind, or tmpfssource (or src) — volume name or host path (for bind mounts)target (or dst) — path inside the containerreadonly — makes the mount read-onlyBoth syntaxes work; --mount is preferred in scripts and documentation for clarity.
Create a named volume:
docker volume create my-data
List all volumes:
docker volume ls
Inspect a volume (shows the mount point on the host):
docker volume inspect my-data
Remove a volume:
docker volume rm my-data
Remove all unused volumes:
docker volume prune
Let us demonstrate volumes with our Nginx container. We will create a volume, write content into it from a temporary container, then serve that content with Nginx — and show that the content survives a container replacement.
docker volume create web-content
docker run --rm \
--mount type=volume,source=web-content,target=/data \
alpine sh -c 'echo "<h1>Content from a volume</h1>" > /data/index.html'
This starts a temporary Alpine container, mounts the volume at /data, writes a file, and immediately exits and removes itself (--rm). The volume and its content persist.
docker run -d \
--name nginx-volume \
-p 8080:80 \
--mount type=volume,source=web-content,target=/usr/share/nginx/html \
nginx:alpine
Open http://localhost:8080 — you see the page from the volume.
docker rm -f nginx-volume
docker run -d \
--name nginx-volume-new \
-p 8080:80 \
--mount type=volume,source=web-content,target=/usr/share/nginx/html \
nginx:alpine
Open http://localhost:8080 again. The same page is still there. The volume outlived the container.
docker rm -f nginx-volume-new
docker volume rm web-content
| Volumes | Bind Mounts | |
|---|---|---|
| Managed by Docker | Yes | No |
| Portable across machines | Yes (with volume drivers) | No (path must exist on host) |
| Best for production data | Yes | No |
| Best for dev code sharing | No | Yes |
| Access from host directly | Via docker volume inspect |
Direct filesystem path |
| Works on Windows containers | Yes | Limited |
In this article we covered:
--mount syntax vs the older -v flagcreate, ls, inspect, rm, pruneThe next article introduces Docker Compose: how to manage a multi-container application with a single YAML file instead of juggling multiple docker run commands.
If you enjoyed this article, don’t forget to give it a clap 👏, share it with your friends 🔗, and follow me for more tips and tutorials on software development 📘. Your support helps me create more content like this — thank you! 🙌