如何使用docker compose v3在容器中直接装载NFS共享/卷
我有一个v3的compose文件,其中有3个服务共享/使用同一卷。在使用swarm模式时,我们需要创建额外的容器和卷来管理集群中的服务 我计划使用NFS服务器,这样单个NFS共享将直接装载到集群中的所有主机上 我发现了以下两种方法,但需要在docker主机上执行额外的步骤-如何使用docker compose v3在容器中直接装载NFS共享/卷,docker,docker-compose,docker-swarm,docker-swarm-mode,Docker,Docker Compose,Docker Swarm,Docker Swarm Mode,我有一个v3的compose文件,其中有3个服务共享/使用同一卷。在使用swarm模式时,我们需要创建额外的容器和卷来管理集群中的服务 我计划使用NFS服务器,这样单个NFS共享将直接装载到集群中的所有主机上 我发现了以下两种方法,但需要在docker主机上执行额外的步骤- 在主机上使用“fstab”或“Mount”命令装载NFS共享,然后将其用作docker服务的主机卷 使用Netshare插件- 是否有一种标准方法可以让我通过在docker主机上只执行几个/不执行步骤(我知道无论如何都需
- 在主机上使用“fstab”或“Mount”命令装载NFS共享,然后将其用作docker服务的主机卷
- 使用Netshare插件-
是否有一种标准方法可以让我通过在docker主机上只执行几个/不执行步骤(我知道无论如何都需要“NFS common”包)就可以使用docker compose v3直接使用/装载NFS共享?是的,您可以从compose文件直接引用NFS:
volumes:
db-data:
driver: local
driver_opts:
type: nfs
o: addr=$SOMEIP,rw
device: ":$PathOnServer"
以类似的方式,您可以在每个主机上创建一个nfs卷
docker volume create --driver local --opt type=nfs --opt o=addr=$SomeIP,rw --opt device=:$DevicePath --name nfs-docker
在发现这是大量未记录的情况下,下面是使用stack和docker compose装载NFS卷的正确方法 最重要的是,您需要使用
版本:“3.2”
或更高版本。如果你不这样做,你会有奇怪的和不明显的错误
第二个问题是卷的定义更改时,卷不会自动更新。这会让你陷入一个兔子洞,认为你的改变是不正确的,而这些改变只是没有被应用。确保您docker rm VOLUMENAME
它可能在任何地方,就好像该卷存在一样,它不会被验证
第三个问题更像是NFS问题—如果NFS文件夹不存在,则不会在服务器上创建该文件夹。这就是NFS的工作方式。在你做任何事情之前,你需要确保它存在
(除非您确信自己知道自己在做什么,否则不要删除'soft'和'nolock'。如果您的NFS服务器不在,这将阻止docker冻结)
下面是一个完整的示例:
[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]#
现在,在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:~#
此卷将在运行堆栈的任何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:~#
我的AWS EFS解决方案有效:
sudo-apt-get-install-y-nfs-common
将驱动程序选项类型更改为NFS4解决了我的问题
volumes:
my-nfs-share:
driver: local
driver_opts:
type: "nfs4"
o: "addr=172.24.0.107,rw"
device: ":/mnt/sharedwordpress"
根据我需要如何使用该卷,我有以下3个选项 首先,您可以直接创建命名卷,并将其用作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
接下来是--mount
语法,该语法在docker-run
和docker-service-create
中起作用。这是一个相当长的选项,当您在另一个逗号分隔的选项中嵌入逗号分隔的选项时,您需要向正在运行的命令传递一些引号(转义以便shell不会删除它们)。我倾向于将其用于需要访问NFS的一次性容器(例如,用于设置NFS目录的实用程序容器):
最后,您可以在撰写文件中定义命名卷。执行此操作时需要注意的一点是,卷名只创建一次,不随任何更改而更新。因此,如果您需要修改命名卷,您将需要给它一个新名称
# 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"
...
在每个示例中:
- 类型设置为
,而不是nfs
。这是因为docker在nfs4
字段上提供了一些很好的功能,但仅适用于addr
类型nfs
是传递给装载系统调用的选项。Linux中的mount syscall和mount命令之间的一个区别是设备将o
之前的部分移动到:
选项中addr
用于设置NFS版本。这避免了操作系统首先尝试其他NFS版本时的延迟nfsvers
- 当您使用
时,type=nfs
可能是一个DNS名称,而不仅仅是一个IP地址。如果您有多个VPC,并且具有使用相同DNS名称的不同NFS服务器,或者如果您希望在将来调整NFS服务器而不更新每个卷装载,那么这将非常有用addr
- 其他选项如
(读写)可以传递到rw
选项o
字段是远程NFS服务器上的路径。前导冒号是必需的。这是mount命令如何将IP地址移动到syscall的device
字段的工件。在将卷装入容器之前,远程主机上必须存在此目录addr
- 在
语法中,--mount
字段是容器内的路径。对于命名卷,您可以在dst
命令的卷装载右侧(用简短语法)设置此路径docker run-v
如果访问远程NFS卷时遇到权限问题,我遇到的一个常见原因是容器以root身份运行,NFS服务器设置为root squash(将所有root访问权更改为nobody用户)。您需要将容器配置为作为已知的非根UID运行,该UID可以访问NFS服务器上的目录,或者在NFS服务器上禁用根挤压。我正在将NFS与compose v3.1一起使用。你认为什么样的问题?由于使用soft和nolock,可能会导致数据损坏吗?这些不应该在您的asnwer中解决吗?@herm也许xrobau提到多个副本与同一nfs服务器通信。“soft”让IO被中断nolock'让flock()调用始终成功。如果您在NFS上依赖flock()和多个用户,那么您将非常 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]:/
volumes:
my-nfs-share:
driver: local
driver_opts:
type: "nfs4"
o: "addr=172.24.0.107,rw"
device: ":/mnt/sharedwordpress"
# 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
...
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"
...