A volume is a directory on the host filesystem, bind-mounted into the container’s namespace.


What Actually Happens

When Docker creates a named volume, it makes a directory on the host:

/var/lib/docker/volumes/<volume-name>/_data/

That’s it. A normal directory. No special filesystem, no format, no encryption — you could ls it from the host right now.

When a container mounts it, the kernel performs a bind mount — a Linux feature that makes a directory appear at a second location in the filesystem tree simultaneously:

host:      /var/lib/docker/volumes/mydata/_data/
               ↕  (same inodes, same blocks)
container: /app/data/

Both paths point to the exact same inodes and disk blocks. There’s no copying, no syncing — it’s one directory visible from two places at once. Writes from the container are immediately visible on the host, and vice versa.


How This Differs from the Container’s Writable Layer

The OverlayFS writable layer (the container’s copy-on-write layer) lives inside Docker’s overlay stack and is destroyed when the container is removed. A bind-mounted volume sits outside that stack entirely — it bypasses OverlayFS and goes straight to the host filesystem. That’s why data survives container removal.


The Three Storage Types at OS Level

TypeOS mechanismLives atSurvives container removal
VolumeBind mount → host dir/var/lib/docker/volumes/Yes
Bind mountBind mount → host dirWherever you specifyYes
tmpfstmpfs kernel mountRAM onlyNo (gone on stop)

Volume vs Bind Mount — What’s the Difference?

Functionally identical at the kernel level — both are bind mounts. The difference is who manages the directory:

  • Volume — Docker creates and manages the directory; you reference it by name (-v mydata:/app/data)
  • Bind mount — you specify an exact host path yourself (-v /home/user/code:/app)

In practice: use named volumes for databases and persistent application data. Use bind mounts in development to mount your source code into the container.


One sentence: a volume is a host directory bind-mounted into the container’s filesystem namespace — the kernel exposes the same inodes at two paths simultaneously, with no virtualisation or copying involved.


See Also