简体   繁体   English

如何使用 docker compose v3 在容器中直接挂载 NFS 共享/卷

[英]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 主机上执行额外的步骤 -

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 rundocker 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:在这些示例中的每一个中:

  • Type is set to nfs , not nfs4 .类型设置为nfs ,而不是nfs4 This is because docker provides some nice functionality on the addr field, but only for the nfs type.这是因为 docker 在addr字段上提供了一些不错的功能,但仅适用于nfs类型。
  • The 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. mount 系统调用和 Linux 中的 mount 命令之间的一个区别是设备将:之前的部分移到了addr选项中。
  • nfsvers is used to set the NFS version. nfsvers用于设置 NFS 版本。 This avoids delays as the OS tries other NFS versions first.这避免了操作系统首先尝试其他 NFS 版本时的延迟。
  • addr may be a DNS name when you use type=nfs , rather than only an IP address.当您使用type=nfsaddr可能是 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.如果您有多个 VPC 和使用相同 DNS 名称的不同 NFS 服务器,或者如果您想在未来调整 NFS 服务器而不更新每个卷挂载,则非常有用。
  • Other options like rw (read-write) can be passed to the o option.其他选项如rw (读写)可以传递给o选项。
  • The device field is the path on the remote NFS server. device字段是远程 NFS 服务器上的路径。 The leading colon is required.前导冒号是必需的。 This is an artifact of how the mount command moves the IP address to the addr field for the syscall.这是 mount 命令如何将 IP 地址移动到系统调用的addr字段的工件。 This directory must exist on the remote host prior to the volume being mounted into a container.在将卷装入容器之前,该目录必须存在于远程主机上。
  • In the --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 解决方案有效:

  1. Create EFS (don't forget to open NFS port 2049 at security group) 创建 EFS (不要忘记在安全组打开 NFS 端口 2049)
  2. Install nfs-common package:安装 nfs-common 包:

    sudo apt-get install -y nfs-common

  3. Check if your efs works:检查您的 efs 是否有效:

     mkdir efs-test-point mkdir 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-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触摸 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-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

    ls -la efs-test-point/

    file 1.txt must exists文件 1.txt 必须存在

  4. 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.

相关问题 NFS 共享卷不会挂载到 Docker 容器 - NFS Share Volume wont mount to Docker container 如何使用 docker-compose 将 Azure 文件共享挂载为容器组的卷? - How to mount Azure File Share as Volume for Container Group using docker-compose? docker-compose v3在多个容器之间共享相同的卷安装位置 - docker-compose v3 share the same volume mount locations between multiple containers 如何使用 docker 组合将主机目录作为卷安装在 docker 容器中 - How to mount a host directory as volume in docker container using docker compose 如何使用docker-compose将localhost卷挂载到docker容器 - how to mount localhost volume to a docker container using docker-compose 如何在Kubernetes中直接挂载外部NFS共享/卷(1.10.3) - How to directly mount external NFS share/volume in kubernetes(1.10.3) Docker撰写v3:卷类型mount和bind之间的区别 - Docker compose v3: The difference between volume type mount and bind 如何在Compose v3中将卷从一个容器装入另一个容器? - How do I mount a volume from one container into another one in Compose v3? 是否可以使用 docker-compose 在同一个容器中安装一个安装和卷? - Is it possible to have a mount and volume in the same container using docker-compose? 在 docker-compose 中挂载 NFS 卷时连接超时 - Connection timed out when mount NFS volume in docker-compose
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM