Mounting a NFS Directory into Host Volume that is shared with Docker

This happens because the volume is using private mount propagation. This means that once the mount happens, any changes that happen on the origin side (e.g. the "host" side in the case of Docker) will not be visible underneath the mount.

There are a couple of ways to handle this:

  1. Do the NFS mount first, then start the container. The mount will propagate to the container, however as before any changes to the mount will not be seen by the container (including unmounts).

  2. Use "slave" propagation. This means that once the mount is created, any changes on the origin side (docker host) will be able to be seen in the target (in the container). If you happen to be doing nested mounts, you'll want to use rslave (r for recursive).

There is also "shared" propagation. This mode would make changes to the mountpoint from inside the container propagate to the host, as well as the other way around. Since your user wouldn't even have privileges to make such changes (unless you add CAP_SYS_ADMIN), this is probably not what you want.

You can set the propagation mode when creating the mount like so:

$ docker run -v /foo:/bar:private

The other alternative would be to use a volume rather than a host mount. You can do this like so:

$ docker volume create \
    --name mynfs \
    --opt type=nfs \
    --opt device=:<nfs export path> \
    --opt o=addr=<nfs host> \
$ docker run -it -v mynfs:/foo alpine sh

This will make sure to always mount in the container for you, doesn't rely on having the host setup in some specific way or dealing with mount propagation.
note: the : at the front of the device path is required, just something weird about the nfs kernel module.
note: Docker does not currently resolve <nfs host> from a DNS name (it will in 1.13) so you will need to supply the ip address here.

More details on "shared subtree" mounts:

Enable shared mount propagation on the volume by adding the :shared flag at the end of the volume argument:

docker run --rm -it -v /tmp:/mnt/tmp:shared alpine sh

If Docker was installed through a package manager or install script for systemd, you may need to adjust the MountFlags daemon argument. To do that, locate the docker.service file:

$ sudo find /etc -name "docker.service"

In my case on Ubuntu 16.04, it was located at /etc/systemd/system/ Edit this file with vi or nano, and ensure that the MountFlags option reads:


Save the file, reload the daemon args, and restart docker:

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

Now you should be able to set the shared mount propagation flag on volumes when using "docker run".

Starting from docker 17.06, you can mount NFS shares to the container directly when you run it, without the need of extra capabilities

export NFS_VOL_NAME=mynfs NFS_LOCAL_MNT=/mnt/mynfs NFS_SHARE=/my/server/path NFS_OPTS=vers=4,soft

docker run --mount \
  "src=$NFS_VOL_NAME,dst=$NFS_LOCAL_MNT,volume-opt=device=:$NFS_SHARE,\"volume-opt=o=addr=$NFS_SERVER,$NFS_OPTS\",type=volume,volume-driver=local,volume-opt=type=nfs" \
  busybox ls $NFS_LOCAL_MNT

Alternatively, you can create the volume before the container:

docker volume create --driver local \
  --opt type=nfs --opt o=addr=$NFS_SERVER,$NFS_OPTS \
  --opt device=:$NFS_SHARE $NFS_VOL_NAME

docker run --rm -v $NFS_VOL_NAME:$NFS_LOCAL_MNT busybox ls $NFS_LOCAL_MNT

Got the hint from