Linux – Making an NFS mount on the host visible and read-write inside Docker container

dockerlinuxnfs

I am new to Docker and I want to use it to get a controlled compilation environment for my code.

I already have a Docker image with all the tools I need. My problem at the moment is as follows:

  • I have my code in the host machine, inside my home folder that is mounted from an NFS server
  • I want to make this folder visible inside the Docker container with r+w permissions

Here's what I tried first (running the container with the source folder as a volume) and the error I get:

[mbrandalero@machine ~]$ docker run -it --cap-add sys_admin -v "/homes/mbrandalero/src:/usr/local/src/" mbrandalero/my-image bash
/usr/bin/docker-current: Error response from daemon: error while creating mount source path '/homes/mbrandalero/src': mkdir /homes/mbrandalero/src: permission denied.

(apparently it is trying to create the directory on the host side, but it is already there)

Curiously enough, when I try running the container with the whole home folder as a volume, it works but yields a different error (no write permission in the folder):

[mbrandalero@machine ~]$ docker run -it --cap-add sys_admin -v "/homes/mbrandalero/:/usr/local/src/home" mbrandalero/my_image bash
root@46712ad936f2:/usr/local/src# cd home/
bash: cd: home/: Permission denied
root@46712ad936f2:/usr/local/src# ls -lah | grep "\(\.\|home\)"
total 4.0K
drwxr-xr-x  1 root  root    18 May 20 14:50 .
drwxr-xr-x  1 root  root    17 May 15 14:06 ..
drwxr-x--- 30 10031 10031 4.0K May 20 15:03 home

Am I doing it right? What am I missing?

Additional informations:

  • OS: CentOS Linux 7.6
  • Docker version: 1.13.1

UPDATE (1):

Apparently setting a user id when running docker run fixes the issue, but is this the right way of doing it? Running it this way sort of fixed things, but looks odd (I get "I have no name!" as username):

[mbrandalero@machine ~]$ docker run -it --cap-add sys_admin -v "/homes/mbrandalero/:/usr/local/src/home" --user $(id -u) mbrandalero/my_image bash
I have no name!@2efec822e572:/usr/local/src$ cd home/
I have no name!@2efec822e572:/usr/local/src/home$

Best Answer

As you've noted in your update, the UID on the files is not mapped in bind mounts, this is how Linux does bind mounts. You can start the container with a different UID, but this will result in the /etc/passwd inside the container mapping to a different, or even no (in your case), user. There are various options, but my preference is to modify the container's UID with a usermod command that runs inside an entrypoint for the image with my fix-perms script. This needs to be run as root, but you can then use gosu to drop back down to the user when running your commands. I've talked about this in my dockercon presentations.


Note, instead of a bind mount to the host NFS directory, you can also do a volume mount directly the NFS server. Here are several examples of how to do that:

  # create a reusable volume
  $ docker volume create --driver local \
      --opt type=nfs \
      --opt o=nfsvers=4,addr=nfs.example.com,rw \
      --opt device=:/path/to/dir \
      foo

  # or from the docker run command
  $ docker run -it --rm \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=nfs.example.com\",volume-opt=device=:/host/path \
    foo

  # or to create a service
  $ docker service create \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=nfs.example.com\",volume-opt=device=:/host/path \
    foo

  # inside a docker-compose file
  ...
  volumes:
    nfs-data:
      driver: local
      driver_opts:
        type: nfs
        o: nfsvers=4,addr=nfs.example.com,rw
        device: ":/path/to/dir"
  ...
Related Question