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

如何使用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主机上只执行几个/不执行步骤(我知道无论如何都需

我有一个v3的compose文件,其中有3个服务共享/使用同一卷。在使用swarm模式时,我们需要创建额外的容器和卷来管理集群中的服务

我计划使用NFS服务器,这样单个NFS共享将直接装载到集群中的所有主机上

我发现了以下两种方法,但需要在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

是,您可以直接从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:~#

在发现这是大量未记录的情况下,下面是使用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解决方案有效:

  • (不要忘记在安全组中打开NFS端口2049)
  • 安装nfs公用程序包:

    sudo-apt-get-install-y-nfs-common

  • 检查您的efs是否工作:

    mkdir efs-test-point sudo chmod go+rw efs-test-point


  • 我的AWS EFS解决方案有效:

  • (不要忘记在安全组中打开NFS端口2049)
  • 安装nfs公用程序包:

    sudo-apt-get-install-y-nfs-common

  • 检查您的efs是否工作:

    mkdir efs-test-point sudo chmod go+rw efs-test-point


  • 将驱动程序选项类型更改为NFS4解决了我的问题

    volumes:
      my-nfs-share:
        driver: local
        driver_opts:
          type: "nfs4"
          o: "addr=172.24.0.107,rw"
          device: ":/mnt/sharedwordpress"
    

    将驱动程序选项类型更改为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
      ,而不是
      nfs4
      。这是因为docker在
      addr
      字段上提供了一些很好的功能,但仅适用于
      nfs
      类型
    • o
      是传递给装载系统调用的选项。Linux中的mount syscall和mount命令之间的一个区别是设备将
      之前的部分移动到
      addr
      选项中
    • nfsvers
      用于设置NFS版本。这避免了操作系统首先尝试其他NFS版本时的延迟
    • 当您使用
      type=nfs
      时,
      addr
      可能是一个DNS名称,而不仅仅是一个