'How to directly mount NFS share/volume in container using docker compose v3
I have a compose file with v3 where there are 3 services sharing/using the same volume. While using swarm mode we need to create extra containers & volumes to manage our services across the cluster.
I am planning to use NFS server so that single NFS share will get mounted directly on all the hosts within the cluster.
I have found below two ways of doing it but it needs extra steps to be performed on the docker host -
Mount the NFS share using "fstab" or "mount" command on the host & then use it as a host volume for docker services.
Use Netshare plugin - https://github.com/ContainX/docker-volume-netshare
Is there a standard way where i can directly use/mount NFS share using docker compose v3 by performing only few/no steps(I understand that "nfs-common" package is required anyhow) on the docker host?
Solution 1:[1]
Depending on how I need to use the volume, I have the following 3 options.
First, you can create the named volume directly and use it as an external volume in compose, or as a named volume in a docker run or docker service create command.
# 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
Next, there is the --mount syntax that works from docker run and docker service create. This is a rather long option, and when you are embedded a comma delimited option within another comma delimited option, you need to pass some quotes (escaped so the shell doesn't remove them) to the command being run. I tend to use this for a one-off container that needs to access NFS (e.g. a utility container to setup NFS directories):
# 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
Lastly, you can define the named volume inside your compose file. One important note when doing this, the name volume only gets created once, and not updated with any changes. So if you ever need to modify the named volume you'll want to give it a new name.
# inside a docker-compose file
...
services:
example-app:
volumes:
- "nfs-data:/data"
...
volumes:
nfs-data:
driver: local
driver_opts:
type: nfs
o: nfsvers=4,addr=nfs.example.com,rw
device: ":/path/to/dir"
...
In each of these examples:
- Type is set to
nfs, notnfs4. This is because docker provides some nice functionality on theaddrfield, but only for thenfstype. - The
oare the options that gets passed to the mount syscall. One difference between the mount syscall and the mount command in Linux is the device has the portion before the:moved into anaddroption. nfsversis used to set the NFS version. This avoids delays as the OS tries other NFS versions first.addrmay be a DNS name when you usetype=nfs, rather than only an IP address. Very useful if you have multiple VPC's with different NFS servers using the same DNS name, or if you want to adjust the NFS server in the future without updating every volume mount.- Other options like
rw(read-write) can be passed to theooption. - The
devicefield is the path on the remote NFS server. The leading colon is required. This is an artifact of how the mount command moves the IP address to theaddrfield for the syscall. This directory must exist on the remote host prior to the volume being mounted into a container. - In the
--mountsyntax, thedstfield is the path inside the container. For named volumes, you set this path on the right side of the volume mount (in the short syntax) on yourdocker run -vcommand.
If you get permission issues accessing a remote NFS volume, a common cause I've encountered is containers running as root, with the NFS server set to root squash (changing all root access to the nobody user). You either need to configure your containers to run as a well known non-root UID that has access to the directories on the NFS server, or disable root squash on the NFS server.
Solution 2:[2]
Yes you can directly reference an NFS from the compose file:
volumes:
db-data:
driver: local
driver_opts:
type: nfs
o: addr=$SOMEIP,rw
device: ":$PathOnServer"
And in an analogous way you could create an nfs volume on each host.
docker volume create --driver local --opt type=nfs --opt o=addr=$SomeIP,rw --opt device=:$DevicePath --name nfs-docker
Solution 3:[3]
My solution for AWS EFS, that works:
- Create EFS (don't forget to open NFS port 2049 at security group)
Install nfs-common package:
sudo apt-get install -y nfs-commonCheck if your efs works:
mkdir efs-test-point sudo chmod go+rw efs-test-point
sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport [YOUR_EFS_DNS]:/ efs-test-point
touch efs-test-point/1.txt sudo umount efs-test-point/ ls -la efs-test-point/
directory must be empty
sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport [YOUR_EFS_DNS]:/ efs-test-point
ls -la efs-test-point/file 1.txt must exists
Configure docker-compose.yml file:
services: sidekiq: volumes: - uploads_tmp_efs:/home/application/public/uploads/tmp ... volumes: uploads_tmp_efs: driver: local driver_opts: type: nfs o: addr=[YOUR_EFS_DNS],nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 device: [YOUR_EFS_DNS]:/
Solution 4:[4]
My problem was solved with changing driver option type to NFS4.
volumes:
my-nfs-share:
driver: local
driver_opts:
type: "nfs4"
o: "addr=172.24.0.107,rw"
device: ":/mnt/sharedwordpress"
Solution 5:[5]
If you are using AutoFS too, on docker-compose you may add :shared to all paths, like this:
volumes:
- /some/nfs/mounted:/path:shared
I found this a better approach to my case thanks to a colleague. Our users were having an error stating 'too many symbolic links'...
Cheers!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | BMitch |
| Solution 2 | |
| Solution 3 | super_p |
| Solution 4 | Ullaakut |
| Solution 5 | adRn-s |
