DEV Community

Celso Nery
Celso Nery

Posted on

Part 3: Persisting Data with Volumes

🇧🇷 Artigo em português aqui

Using Docker — Part 3: Persisting Data with Volumes

In Part 2 of this series, we covered the essential commands for operating containers day to day. But there's an important detail: by default, data written inside a container is ephemeral — if the container is removed, that data disappears with it. For stateful applications (databases, user uploads, configuration files), that's a problem. That's what volumes exist to solve.

Bind mount vs. Volume

There are two main ways to persist data outside a container's lifecycle:

  • Bind mount: mounts a specific folder from the host (the machine running Docker) inside the container. You have full control over where the data lives on the host, but you become more dependent on that specific machine's folder structure.
  • Volume: managed by Docker itself, stored in an internal area (/var/lib/docker/volumes/ on Linux). This is the recommended approach for most cases, since it's more portable across environments and easier to back up, inspect, and clean up.

This article focuses on volumes — the recommended approach for professional use.

Creating a volume

To create a named volume that will store an application's data:

docker volume create vol_name
Enter fullscreen mode Exit fullscreen mode

Listing volumes

To see all volumes that already exist on the system:

docker volume ls
Enter fullscreen mode Exit fullscreen mode

Inspecting a volume

To see details about a specific volume — such as the actual path where the data is stored on the host:

docker volume inspect vol_name
Enter fullscreen mode Exit fullscreen mode

Running a container with a volume -v

Using a bind mount

docker run --rm -d -it -v local_folder:remote_folder httpd
Enter fullscreen mode Exit fullscreen mode

Here, local_folder is an absolute path on the host (for example, /home/celso/data), and remote_folder is the path inside the container where that data should appear (for example, /var/www/htdocs/).

Using a created volume

docker run --rm -d -it -v volume_name:remote_folder httpd
Enter fullscreen mode Exit fullscreen mode

In this case, volume_name is the name of the volume created earlier with docker volume create — Docker handles where that data is physically stored.

Removing a volume

If any container is still using the volume, you'll need to remove the container first:

docker rm <container_name>
Enter fullscreen mode Exit fullscreen mode

Then, to remove the volume:

docker volume rm vol_name
Enter fullscreen mode Exit fullscreen mode

Cleaning up unused volumes

Over time, it's common to accumulate orphaned volumes (created by containers that have since been removed). To clean up all volumes not currently used by any container:

docker volume prune
Enter fullscreen mode Exit fullscreen mode

⚠️ This command permanently removes the data of any volume not referenced by an active container — confirm before running this on an environment with important data.

Using NFS volumes

In environments with multiple Docker hosts (or when you want to share data across different servers), you can create a volume pointing to an NFS share instead of local storage:

docker volume create --opt type=nfs --opt o=addr=10.0.0.35,rw,nfsvers=4 --opt device=:/home/nfsshare nfs-volume
Enter fullscreen mode Exit fullscreen mode

Where:

  • type=nfs: sets the volume driver to NFS;
  • o=addr=10.0.0.35,rw,nfsvers=4: NFS server address and mount options (read/write, protocol version);
  • device=:/home/nfsshare: path exported by the NFS server;
  • nfs-volume: name given to the volume in Docker.

This is especially useful in scenarios where multiple containers (possibly on different hosts) need access to the same shared data set.

Next steps

With volumes handling data persistence, the next challenge is communication between containers — especially when an application depends on multiple services (for example, an API that needs to talk to a database). In Part 4 of this series, we'll look at how to create and manage networks in Docker.

Continued in Part 4.

Top comments (0)