skip to content

Docker's built-in `local` volume driver can be given mount options at creation time, and third-party volume plugins can be installed alongside it. Explain what a volume driver is responsible for, what the `local` driver's options let you do, and how you would decide whether a workload needs a plugin driver instead.

level: seniorimportance: nice to knowfreq 33%

answer

  1. driver contract: Create/Mount/Unmount/Remove
  2. scope: local vs global
  3. local --opt maps to mount(8): nfs / tmpfs / none,o=bind
  4. options frozen at creation; mount is lazy
  5. plugin = dependency in the container start path

basics

~20 s

A volume driver is the plugin that creates, mounts and removes the storage behind a volume. The built-in local driver stores data on the host and accepts mount(8)-style options (type=nfs, type=tmpfs, bind). A plugin driver adds remote or cluster-scoped storage — worth it only when containers must move between hosts and keep their data.

solid answer

~60 s

Every volume names a **driver**: the component the daemon calls to create, mount, unmount and remove the underlying storage. `docker volume inspect` shows it. The default is `local`, which keeps data in `/var/lib/docker/volumes/<name>/_data` on that one host. The `local` driver is less limited than its name suggests: its `--opt` keys map onto `mount(8)`, so you can create a volume backed by NFS, by tmpfs, or by a bind to an arbitrary host path: ``` docker volume create --driver local \ --opt type=nfs --opt o=addr=10.0.0.5,rw,nfsvers=4 \ --opt device=:/exports/app app-nfs ``` The mount then happens on the daemon host, and the volume has a stable name and lifecycle rather than being a per-container flag. Plugin drivers (`docker plugin install ...`) exist for cloud block storage and network filesystems, and may be `global`-scoped so a cluster shares one namespace. Adopt one only when you actually need a container to be rescheduled onto another host and find its data there. The costs are real: an extra daemon-level dependency in the container start path, drivers that fall out of maintenance, and a backup story you now own. For a single host, `local` plus a disciplined backup is usually the better engineering call.

code

bash · 15 lines
bash
# NFS-backed named volume
docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=10.0.0.5,rw,nfsvers=4,hard,timeo=600 \
  --opt device=:/exports/app app-nfs

# RAM-backed named volume
docker volume create --driver local \
  --opt type=tmpfs --opt device=tmpfs --opt o=size=256m scratch

# named volume bound to a chosen host path
docker volume create --driver local \
  --opt type=none --opt o=bind --opt device=/srv/app-data app-bind

docker volume inspect app-nfs --format '{{.Driver}} {{.Scope}} {{json .Options}}'

go deeper

for a junior

Know that every volume has a driver, that local is the default and stores data on that host, and that docker volume inspect shows which one is in use.

for a middle

Show the local driver's mount options (NFS, tmpfs, bind), note that options are fixed at creation, and explain that plugin drivers exist for storage that outlives one host.

for a senior

Talk about failure modes: lazy mounts surfacing as unstartable containers, NFS hard-vs-soft behaviour, plugins sitting in the container start path, and unmaintained drivers — plus a decision path that keeps most workloads on local.

for a principal

Frame it as a durability and coupling decision: whether durability comes from the storage layer or from application replication, what a plugin adds to the blast radius and operational surface, and whether engine-level plugins are a dead end given a likely move to CSI-based orchestration.

## What a driver is Docker's volume subsystem is an interface, not an implementation. When you run `docker volume create`, the daemon delegates to a **volume driver** that implements a small contract: `Create`, `Remove`, `Mount`, `Unmount`, `Path`, `Get`, `List`, `Capabilities`. The daemon knows only "give me a host path I can bind into this container's mount namespace, and tell me when I may release it". Everything about where the bytes really live is the driver's business. `docker volume inspect app-data` shows which driver owns a volume, the options it was created with, and its **scope**: `local` (meaningful only on this host) or `global` (the same volume name means the same storage across a cluster). Scope is the property that decides whether rescheduling a workload onto another machine can work. ## The built-in `local` driver Default, always present, no installation. Data lives under `/var/lib/docker/volumes/<name>/_data` on the daemon host — meaning the workload is pinned to that machine. What many engineers miss is that `local` accepts options that map directly onto the Linux `mount` command, so it can front other filesystems: **NFS** ``` docker volume create --driver local \ --opt type=nfs \ --opt o=addr=10.0.0.5,rw,nfsvers=4,hard,timeo=600 \ --opt device=:/exports/app app-nfs ``` The daemon host performs the NFS mount when a container first uses the volume. Containers on several hosts pointed at the same export share data — a poor-man's shared storage with no plugin installed. The `hard`/`timeo` options matter: with a soft mount, an NFS blip surfaces as I/O errors inside the container. **tmpfs** ``` docker volume create --driver local --opt type=tmpfs --opt device=tmpfs \ --opt o=size=256m,uid=1000 scratch ``` A named, reusable RAM-backed volume (distinct from a per-container `--tmpfs` flag). **Bind to a specific host path** ``` docker volume create --driver local \ --opt type=none --opt o=bind --opt device=/srv/app-data app-bind ``` This gives a named, inspectable, labelled object whose data sits at a path you chose — useful when you want volume-shaped lifecycle management over a directory on a dedicated disk. Two constraints to remember: options are **fixed at creation** (no editing later — recreate and copy), and the mount is attempted lazily, so a bad NFS address surfaces as a container that will not start rather than as a failed `volume create`. ## Plugin drivers Installed as managed plugins: ``` docker plugin install vieux/sshfs docker volume create -d vieux/sshfs -o sshcmd=user@host:/data -o password=... remote ``` The ecosystem covers cloud block storage, distributed filesystems and vendor arrays. Swarm additionally supports cluster volumes backed by CSI plugins, where the orchestrator asks the driver to attach storage wherever the task is placed. What you buy: storage that outlives one host, so a container rescheduled elsewhere finds its data; features the local filesystem lacks (snapshots, replication, quotas, encryption at rest managed by the array); and, for `global`-scope drivers, one namespace across the cluster. What you pay: - **A dependency in the container start path.** Plugin down or wedged → containers cannot mount → they will not start. You have added a distributed system beneath your distributed system. - **Maintenance risk.** Many once-popular volume plugins are unmaintained; several vendors moved their investment to CSI for Kubernetes and left the Docker plugin behind. Check commit activity before adopting. - **Operational surface.** Credentials for the storage backend on every host, plugin upgrades coordinated with engine upgrades, driver-specific failure modes to learn, and metrics that your existing monitoring does not collect. - **Backups are still yours.** A replicated array protects against disk failure, not against `DELETE FROM`. Helper-container or application-native backups remain necessary. - **Performance shape changes.** Network storage turns local page-cache-friendly I/O into round trips; latency-sensitive databases feel it. ## The decision Ask, in order: 1. **Must this workload's data survive the loss of one host, or move with the container?** No → `local`, and stop. This covers most single-host deployments, CI, dev, and services whose durability comes from application-level replication (a three-node database replicating over the network wants fast local disks, not shared storage). 2. **If yes, can the application replicate instead?** Application-level replication is usually more predictable than shared block storage and avoids the split-brain risks of shared filesystems. 3. **If shared storage is genuinely required, is NFS via the `local` driver enough?** Often yes, and it costs no plugin — good for shared assets, uploads, artefact caches. 4. **Only then take a plugin**, and require: active maintenance, a documented failure behaviour when the backend is unreachable, a tested restore, and metrics. And note the strategic angle: if you are heading toward orchestration, storage integration there is done through CSI rather than Docker volume plugins, so investing heavily in engine-level plugins can be a dead end. That belongs in the decision, not just the implementation.

  • You created a volume with `--opt type=nfs` and the NFS server address is wrong. When and how does that failure show up?
    Not at creation — `docker volume create` only records metadata and returns success. The mount is attempted when a container first uses the volume, so the failure appears as a container that will not start, with a mount error in the daemon logs. Because options cannot be edited afterwards, the fix is to remove the volume and create it again with the correct `o=addr=...`.
  • What changes about backups when a volume is backed by a replicated storage plugin?
    Almost nothing you can skip. Replication protects against hardware failure, not against a bad migration, an accidental delete, or ransomware, so you still need point-in-time copies — helper-container tarballs or application-native dumps. What can change is the mechanism: a backend with snapshots may give you cheaper, more consistent point-in-time copies, but you must still test restoring one.

The local driver is a filing cabinet in your own office: instant, private, useless once you move desks. A plugin driver is a records department other floors can request from — it follows you anywhere, but if the records department is closed, nobody can start work at all.

saying these in an interview costs you the question

  • Believing the `local` driver can only use local disk — it fronts NFS, tmpfs and arbitrary bind paths via mount options.
  • Thinking driver options can be edited after creation instead of recreating the volume.
  • Adopting a plugin driver for a single-host deployment where a named local volume plus backups would do.
  • Assuming a plugin driver makes data safe, so backups are unnecessary.
  • Confusing volume drivers with storage drivers (overlay2 and friends), which handle image and container layers, not volumes.

context