[英]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.我有一个带有 v3 的 compose 文件,其中有 3 个服务共享\/使用相同的卷。 While using swarm mode we need to create extra containers & volumes to manage our services across the cluster.
在使用 swarm 模式时,我们需要创建额外的容器和卷来跨集群管理我们的服务。
I am planning to use NFS server so that single NFS share will get mounted directly on all the hosts within the cluster.我计划使用 NFS 服务器,以便将单个 NFS 共享直接安装在集群内的所有主机上。
I have found below two ways of doing it but it needs extra steps to be performed on the docker host -我发现了以下两种方法,但它需要在 docker 主机上执行额外的步骤 -
Mount the NFS share using "fstab" or "mount" command on the host & then use it as a host volume for docker services.在主机上使用“fstab”或“mount”命令挂载 NFS 共享,然后将其用作 docker 服务的主机卷。
Use Netshare plugin - https:\/\/github.com\/ContainX\/docker-volume-netshare<\/a>使用 Netshare 插件 -
https:\/\/github.com\/ContainX\/docker-volume-netshare<\/a>
After discovering that this is massively undocumented,here's the correct way to mount a NFS volume using stack and docker compose.在发现这是大量未记录的之后,这里是使用堆栈和 docker compose 挂载 NFS 卷的正确方法。
The most important thing is that you need to be using version: "3.2"
or higher.最重要的是您需要使用
version: "3.2"
或更高版本。 You will have strange and un-obvious errors if you don't.如果你不这样做,你会遇到奇怪的和不明显的错误。
The second issue is that volumes are not automatically updated when their definition changes.第二个问题是当卷的定义发生变化时,卷不会自动更新。 This can lead you down a rabbit hole of thinking that your changes aren't correct, when they just haven't been applied.
这可能会导致您误以为您的更改不正确,因为它们还没有被应用。 Make sure you
docker rm VOLUMENAME
everywhere it could possibly be, as if the volume exists, it won't be validated.确保你在任何可能存在的地方
docker rm VOLUMENAME
,就好像该卷存在一样,它不会被验证。
The third issue is more of a NFS issue - The NFS folder will not be created on the server if it doesn't exist.第三个问题更多是 NFS 问题 - 如果 NFS 文件夹不存在,则不会在服务器上创建它。 This is just the way NFS works.
这就是 NFS 的工作方式。 You need to make sure it exists before you do anything.
在你做任何事情之前,你需要确保它存在。
(Don't remove 'soft' and 'nolock' unless you're sure you know what you're doing - this stops docker from freezing if your NFS server goes away) (除非您确定自己知道自己在做什么,否则不要删除“soft”和“nolock”——如果您的 NFS 服务器消失,这会阻止 docker 冻结)
Here's a complete example:这是一个完整的例子:
[root@docker docker-mirror]# cat nfs-compose.yml
version: "3.2"
services:
rsyslog:
image: jumanjiman/rsyslog
ports:
- "514:514"
- "514:514/udp"
volumes:
- type: volume
source: example
target: /nfs
volume:
nocopy: true
volumes:
example:
driver_opts:
type: "nfs"
o: "addr=10.40.0.199,nolock,soft,rw"
device: ":/docker/example"
[root@docker docker-mirror]# docker stack deploy --with-registry-auth -c nfs-compose.yml rsyslog
Creating network rsyslog_default
Creating service rsyslog_rsyslog
[root@docker docker-mirror]# docker stack ps rsyslog
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
tb1dod43fe4c rsyslog_rsyslog.1 jumanjiman/rsyslog:latest swarm-4 Running Starting less than a second ago
[root@docker docker-mirror]#
Now, on swarm-4:现在,在 swarm-4 上:
root@swarm-4:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d883e0f14d3f jumanjiman/rsyslog:latest "rsyslogd -n -f /e..." 6 seconds ago Up 5 seconds 514/tcp, 514/udp rsyslog_rsyslog.1.tb1dod43fe4cy3j5vzsy7pgv5
root@swarm-4:~# docker exec -it d883e0f14d3f df -h /nfs
Filesystem Size Used Available Use% Mounted on
:/docker/example 7.2T 5.5T 1.7T 77% /nfs
root@swarm-4:~#
This volume will be created ( but not destroyed ) on any swarm node that the stack is running on.该卷将在堆栈运行的任何 swarm 节点上创建(但不会销毁)。
root@swarm-4:~# docker volume inspect rsyslog_example
[
{
"CreatedAt": "2017-09-29T13:53:59+10:00",
"Driver": "local",
"Labels": {
"com.docker.stack.namespace": "rsyslog"
},
"Mountpoint": "/var/lib/docker/volumes/rsyslog_example/_data",
"Name": "rsyslog_example",
"Options": {
"device": ":/docker/example",
"o": "addr=10.40.0.199,nolock,soft,rw",
"type": "nfs"
},
"Scope": "local"
}
]
root@swarm-4:~#
Depending on how I need to use the volume, I have the following 3 options.根据我需要如何使用音量,我有以下 3 个选项。
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.首先,您可以直接创建命名卷并将其用作 compose 中的外部卷,或用作
docker run
或docker service create
命令中的命名卷。
# 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
.接下来是
--mount
语法,它适用于--mount
docker run
和--mount
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.这是一个相当长的选项,当您在另一个逗号分隔选项中嵌入一个逗号分隔选项时,您需要将一些引号(转义以便 shell 不会删除它们)传递给正在运行的命令。 I tend to use this for a one-off container that needs to access NFS (eg a utility container to setup NFS directories):
我倾向于将它用于需要访问 NFS 的一次性容器(例如用于设置 NFS 目录的实用程序容器):
# 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:在这些示例中的每一个中:
nfs
, not nfs4
.nfs
,而不是nfs4
。 This is because docker provides some nice functionality on the addr
field, but only for the nfs
type.addr
字段上提供了一些不错的功能,但仅适用于nfs
类型。o
are the options that gets passed to the mount syscall. o
是传递给挂载系统调用的选项。 One difference between the mount syscall and the mount command in Linux is the device has the portion before the :
moved into an addr
option. :
之前的部分移到了addr
选项中。nfsvers
is used to set the NFS version. nfsvers
用于设置 NFS 版本。 This avoids delays as the OS tries other NFS versions first.addr
may be a DNS name when you use type=nfs
, rather than only an IP address.type=nfs
, addr
可能是 DNS 名称,而不仅仅是 IP 地址。 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.rw
(read-write) can be passed to the o
option.rw
(读写)可以传递给o
选项。device
field is the path on the remote NFS server. device
字段是远程 NFS 服务器上的路径。 The leading colon is required.addr
field for the syscall.addr
字段的工件。 This directory must exist on the remote host prior to the volume being mounted into a container.--mount
syntax, the dst
field is the path inside the container.--mount
语法中, dst
字段是容器内的路径。 For named volumes, you set this path on the right side of the volume mount (in the short syntax) on your docker run -v
command.docker run -v
命令的卷安装右侧(以简短语法)设置此路径。 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).如果您在访问远程 NFS 卷时遇到权限问题,我遇到的一个常见原因是容器以 root 身份运行,NFS 服务器设置为 root squash(将所有 root 访问权限更改为 nobody 用户)。 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.
您要么需要将容器配置为作为众所周知的非根 UID 运行,该 UID 可以访问 NFS 服务器上的目录,或者在 NFS 服务器上禁用根压缩。
Yes you can directly reference an NFS from the compose file:是的,您可以直接从撰写文件中引用 NFS:
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.以类似的方式,您可以在每个主机上创建一个 nfs 卷。
docker volume create --driver local --opt type=nfs --opt o=addr=$SomeIP,rw --opt device=:$DevicePath --name nfs-docker
My solution for AWS EFS, that works:我的 AWS EFS 解决方案有效:
Install nfs-common package:安装 nfs-common 包:
sudo apt-get install -y nfs-common
Check if your efs works:检查您的 efs 是否有效:
mkdir efs-test-pointmkdir efs-测试点\nsudo chmod go+rw efs-test-point
须藤 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-pointsudo 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触摸 efs-test-point/1.txt\nsudo umount efs-test-point/
须藤 umount efs-测试点/\nls -la efs-test-point/
ls -la efs-测试点/
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-pointsudo 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
文件 1.txt 必须存在
Configure docker-compose.yml file:配置 docker-compose.yml 文件:
services:服务:\n sidekiq:
小伙伴:\n volumes:
卷:\n - uploads_tmp_efs:/home/application/public/uploads/tmp
-uploads_tmp_efs:/home/application/public/uploads/tmp\n ...
...\nvolumes:
卷:\n uploads_tmp_efs:
上传_tmp_efs:\n driver: local
司机:本地\n driver_opts:
驱动程序选择:\n type: nfs
类型:nfs\n o: addr=[YOUR_EFS_DNS],nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2
o: addr=[YOUR_EFS_DNS],nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2\n device: [YOUR_EFS_DNS]:/
设备:[YOUR_EFS_DNS]:/
My problem was solved with changing driver option type to NFS4.我的问题通过将驱动程序选项类型更改为 NFS4 解决了。
volumes:
my-nfs-share:
driver: local
driver_opts:
type: "nfs4"
o: "addr=172.24.0.107,rw"
device: ":/mnt/sharedwordpress"
If you are using AutoFS too, on docker-compose<\/code> you may add
:shared<\/code> to all paths, like this:
如果您也在使用 AutoFS,则可以在
docker-compose<\/code>上将
:shared<\/code>添加到所有路径,如下所示:
volumes:
- /some/nfs/mounted:/path:shared
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.