将NFS目录挂载到与Docker共享的主机卷中


8

考虑以下Docker容器:

docker run --rm -it -v /tmp:/mnt/tmp alpine sh

这会将主机目录/ tmp装入高山容器内的/ mnt / tmp中。

现在,在主机系统上,我将NFS卷挂载到/ tmp目录:

mkdir /tmp/nfs
mount -t nfs4 192.168.1.100:/data /tmp/nfs

该挂载在主机系统上工作,并且看到以下内容:

# ls /tmp/nfs
file1 file2 file3
#

但是在Docker容器上,我看到一个空白目录:

# ls /mnt/tmp/nfs
#

我知道我可以通过直接在Docker容器中进行挂载来解决此问题。但是我真的很想知道为什么挂载可以在主机容器上工作而不在docker容器上工作吗?


您可能需要描述您的操作系统,泊坞窗版本等。我刚刚在Extras中使用Centos 7和docker 1.10进行了尝试,并且按预期工作;NFS挂载的内容出现在一个debian / jessie容器中。还有您是否具有安全控制(例如SELinux)和其他标志。
史蒂芬·哈里斯

我正在将Ubuntu 16.04与Docker版本1.12.0-dev结合使用,没有额外的安全控件。仅在创建Alpine容器后进行NFS挂载时,该问题才会出现。如果在创建Alpine容器之前进行NFS挂载,则会按预期看到它。
卡雷布(Caleb)2016年

Answers:


15

发生这种情况是因为该卷正在使用private挂载传播。这意味着一旦挂载发生,在挂载下方将看不到在源端发生的任何更改(例如,对于Docker,为“主机”端)。

有两种方法可以解决此问题:

  1. 首先执行NFS挂载,然后启动容器。安装将传播到容器,但是与之前一样,容器不会看到对安装的任何更改(包括卸载)。

  2. 使用“从属”传播。这意味着一旦创建了挂载,就可以在目标(容器中)中看到原始端(docker主机)上的任何更改。如果您碰巧正在执行嵌套挂载,则需要使用rslaver用于递归)。

也存在“共享”传播。此模式将使容器内部对安装点的更改传播到主机,反之亦然。由于您的用户甚至没有权限进行此类更改(除非您添加CAP_SYS_ADMIN),所以这可能不是您想要的。

您可以在创建挂载时设置传播模式,如下所示:

$ docker run -v /foo:/bar:private

另一种选择是使用卷而不是主机挂载。您可以这样做:

$ docker volume create \
    --name mynfs \
    --opt type=nfs \
    --opt device=:<nfs export path> \
    --opt o=addr=<nfs host> \
    mynfs
$ docker run -it -v mynfs:/foo alpine sh

这将确保始终为您安装在容器中,而不依赖于以某种特定方式设置主机或处理安装传播。
注意:设备路径的前面是必需的,只是关于nfs内核模块的一些怪异的东西。
注意:Docker当前不<nfs host>使用DNS名称解析(它将在1.13中解析),因此您需要在此处提供ip地址。

有关“共享子树”安装的更多详细信息:https : //www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt


很好的答案。您能否将其编辑为更多的独立答案,以解释如何在Docker Daemon中设置MountFlags = slave而不依赖于其他答案的上下文。然后,我将其切换为接受的答案。
卡莱布

4

通过在volume参数的末尾添加:shared标志,在卷上启用共享安装传播:

docker run --rm -it -v /tmp:/mnt/tmp:shared alpine sh

如果Docker是通过软件包管理器或systemd的安装脚本安装的,则可能需要调整MountFlags守护程序参数。为此,找到docker.service文件:

$ sudo find /etc -name "docker.service"

在我的Ubuntu 16.04上,它位于/etc/systemd/system/multi-user.target.wants/docker.service中。使用vi或nano编辑此文件,并确保MountFlags选项显示为:

MountFlags=shared

保存文件,重新加载守护程序args,然后重新启动docker:

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

现在,使用“ docker run”时,您应该能够在卷上设置共享的挂载传播标志。


3

从docker 17.06开始,您可以在运行NFS共享时将其直接挂载到容器上,而无需额外的功能

export NFS_VOL_NAME=mynfs NFS_LOCAL_MNT=/mnt/mynfs NFS_SERVER=my.nfs.server.com NFS_SHARE=/my/server/path NFS_OPTS=vers=4,soft

docker run --mount \
  "src=$NFS_VOL_NAME,dst=$NFS_LOCAL_MNT,volume-opt=device=:$NFS_SHARE,\"volume-opt=o=addr=$NFS_SERVER,$NFS_OPTS\",type=volume,volume-driver=local,volume-opt=type=nfs" \
  busybox ls $NFS_LOCAL_MNT

或者,您可以在容器之前创建卷:

docker volume create --driver local \
  --opt type=nfs --opt o=addr=$NFS_SERVER,$NFS_OPTS \
  --opt device=:$NFS_SHARE $NFS_VOL_NAME

docker run --rm -v $NFS_VOL_NAME:$NFS_LOCAL_MNT busybox ls $NFS_LOCAL_MNT

https://github.com/moby/moby/issues/28809获得了提示

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.