【问题标题】:Can't expose a fuse based volume to a Docker container无法将基于熔断器的卷公开给 Docker 容器
【发布时间】:2015-05-06 02:06:24
【问题描述】:

我正在尝试为我的 docker 容器提供大量加密文件系统供内部使用。 这个想法是容器将像往常一样写入卷,但实际上主机将在将数据写入文件系统之前对其进行加密。

我正在尝试使用 EncFS - 它在主机上运行良好,例如:

encfs /encrypted /visible

我可以将文件写入 /visible,并且这些文件会被加密。 但是,当尝试以 /visible 作为卷运行容器时,例如:

docker run -i -t --privileged -v /visible:/myvolume imagename bash

我确实在容器中获得了一个卷,但它位于原始 /encrypted 文件夹中,而不是通过 EncFS。如果我从/visible 卸载EncFS,我可以看到容器写入的文件。不用说/encrypted 是空的。

有没有办法让 docker 通过 EncFS 挂载卷,而不是直接写入文件夹? 相反,当我使用 NFS 挂载作为卷时,docker 工作正常。它写入网络设备,而不是我安装设备的本地文件夹。

谢谢

【问题讨论】:

    标签: linux docker fuse


    【解决方案1】:

    您可以通过将挂载调用包装在nsenter 中以将其挂载到与 docker 守护进程相同的 Linux 挂载命名空间中来解决此问题,例如。

    nsenter -t "$PID_OF_DOCKER_DAEMON" encfs ...
    

    问题是这种方法是否能在守护进程重启后继续存在。 ;-)

    【讨论】:

      【解决方案2】:

      这肯定是因为您在主机安装挂载点之前启动了 docker 守护进程。在这种情况下,目录名称的 inode 仍然指向主机本地磁盘:

      ls -i /mounts/
      1048579 s3-data-mnt
      

      那么如果你使用 s3fs 之类的 fuse 守护进程挂载:

      /usr/local/bin/s3fs -o rw -o allow_other -o iam_role=ecsInstanceRole /mounts/s3-data-mnt
      ls -i
      1 s3-data-mnt
      

      我的猜测是 docker 对 inode 的目录名称进行了一些引导缓存(对此了解更多的人无法填写此空白)。

      您的评论是正确的。如果您在挂载完成后简单地重新启动 docker,您的卷将正确地从主机共享到您的容器。 (或者您可以简单地延迟启动 docker,直到所有挂载都完成挂载)

      有趣的是(但现在对我来说已经完成了)是,在退出容器并在主机上卸载挂载点时,我从容器内到共享卷的所有写入都神奇地出现了(它们被存储在主机本地磁盘上的inode):

      [root@host s3-data-mnt]# echo foo > bar
      [root@host s3-data-mnt]# ls /mounts/s3-data-mnt
      total 6
      1 drwxrwxrwx  1 root root    0 Jan  1  1970 .
      4 dr-xr-xr-x 28 root root 4096 Sep 16 17:06 ..
      1 -rw-r--r--  1 root root    4 Sep 16 17:11 bar
      [root@host s3-data-mnt]# docker run -ti -v /mounts/s3-data-mnt:/s3-data busybox /bin/bash
      root@5592454f9f4d:/mounts/s3-data# ls -als
      total 8
      4 drwxr-xr-x  3 root root 4096 Sep 16 16:05 .
      4 drwxr-xr-x 12 root root 4096 Sep 16 16:45 ..
      root@5592454f9f4d:/s3-data# echo baz > beef
      root@5592454f9f4d:/s3-data# ls -als
      total 9
      4 drwxr-xr-x  3 root root 4096 Sep 16 16:05 .
      4 drwxr-xr-x 12 root root 4096 Sep 16 16:45 ..
      1 -rw-r--r--  1 root root    4 Sep 16 17:11 beef
      root@5592454f9f4d:/s3-data# exit
      exit
      [root@host s3-data-mnt]# ls /mounts/s3-data-mnt
      total 6
      1 drwxrwxrwx  1 root root    0 Jan  1  1970 .
      4 dr-xr-xr-x 28 root root 4096 Sep 16 17:06 ..
      1 -rw-r--r--  1 root root    4 Sep 16 17:11 bar
      [root@host /]# umount -l s3-data-mnt
      [root@host /]# ls -als
      [root@ip-10-0-3-233 /]# ls -als /s3-stn-jira-data-mnt/
      total 8
      4 drwxr-xr-x  2 root root 4096 Sep 16 17:28 .
      4 dr-xr-xr-x 28 root root 4096 Sep 16 17:06 ..
      1 -rw-r--r--  1 root root    4 Sep 16 17:11 bar
      

      【讨论】:

        【解决方案3】:

        我无法在本地复制您的问题。如果我尝试将 encfs 文件系统公开为 Docker 卷,则尝试启动容器时会出错:

        FATA[0003] Error response from daemon: Cannot start container <cid>:
        setup mount namespace stat /visible: permission denied 
        

        所以你有可能发生了一些不同的事情。无论如何,这就是解决我的问题的方法:

        默认情况下,FUSE 只允许挂载文件系统的用户访问该文件系统。当您运行 Docker 容器时,该容器最初以 root 运行。

        您可以在挂载 FUSE 文件系统时使用 allow_rootallow_other 挂载选项。例如:

        $ encfs -o allow_root /encrypted /other
        

        这里,allow_root 将允许 root 用户访问挂载点,而allow_other 将允许任何人访问挂载点(前提是目录上的 Unix 权限允许他们访问)。

        如果我使用 allow_root 通过 encfs 文件系统挂载,则我可以将该文件系统公开为 Docker 卷并且该文件系统的内容从容器内部正确可见。

        【讨论】:

        • 感谢您的回答以及评估问题所花费的时间。花了很多时间后,我发现根本问题要简单得多:似乎每次向系统添加新挂载时,我都需要重新启动 Docker 服务。听起来不太合乎逻辑,但这解决了它。除非我这样做,否则 Docker 将始终使用启动时的挂载或文件夹 - 如果那里没有挂载,它确实会写入底层本地文件夹。
        猜你喜欢
        • 2016-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-27
        • 2020-05-23
        • 2021-02-03
        相关资源
        最近更新 更多