在一个 Docker 容器中的 Mount SMB/CIFS 共享

我有一个在 Docker 容器中运行的 Web 应用程序。此应用程序需要访问公司文件服务器上的一些文件(带有 ActiveDirectory 网域控制器的 Windows 服务器)。我试图访问的文件是为我们的客户创建的图像文件,Web 应用程序将它们显示为客户投资组合的一部分。

在我的开发机器上,我通过 /etc/fstab中的条目安装了适当的文件夹,并且主机安装点通过 --volume参数安装在 Docker 容器中。这样很好。

现在我尝试组装一个生产容器,它将在不同的服务器上运行,并且不依赖于在主机上安装的 CIFS 共享。因此,我试图添加适当的条目到 /etc/fstab文件在容器和安装他们与 mount -a。我得到 mount error(13): Permission denied

网上的一点研究让我找到了 这篇关于 Docker 安全的文章。如果我没有理解错的话,似乎 Docker 显式地拒绝了在容器中挂载文件系统的能力。我尝试以只读方式挂载股票,但这种做法(不出所料)也失败了。

我有两个问题:

  1. 我的理解是否正确,Docker 防止在容器内使用 mount

  2. 有人能想到另一种方法来完成这个 没有挂载在主机上的 CIFS 共享,然后挂载在 Docker 容器的主机文件夹?

114323 次浏览

是的,作为安全措施,Docker 阻止您在容器内安装远程卷。如果您信任您的图像和运行它们的人,那么您可以使用 --privileged标志和 docker run来禁用这些安全措施。

此外,还可以将 --cap-add--cap-drop组合起来,使容器只具备它实际需要的功能。(见文档) SYS_ADMIN功能是授予挂载特权的功能。

  1. 是的
  2. 有一个封闭的问题 容器中的 mount. cifs

Https://github.com/docker/docker/issues/22197

根据哪个加法

--cap-add SYS_ADMIN --cap-add DAC_READ_SEARCH

将使 mount-t cifs 可操作。

我试过了:

mount -t cifs //<host>/<path> /<localpath> -o user=<user>,password=<user>

然后在容器内工作

您可以使用 smbclient命令(Samba 包的一部分)从 Docker 容器内访问 SMB/CIFS 服务器,而无需挂载它,这与使用 curl下载或上传文件的方式相同。

StackExchange Unix上有一个问题是关于这个的,但简而言之:

smbclient //server/share -c 'cd /path/to/file; put myfile'

对于多个文件,可以使用 -T选项来创建或提取 .tar归档文件,但是这看起来需要两个步骤(一个是创建 .tar,另一个是在本地提取它)。我不确定你是否可以用管子一步完成。

你可以使用一个 Netshare Docker 卷插件,它允许 以卷的形式挂载远程 CIFS/Samba。

不要为了挂载一个共享而暴露许多端口,从而降低容器的安全性。或者将其运行为 --privileged

我是这样解决这个问题的:

  • 首先将卷挂载到运行 docker 的服务器上。

sudo mount -t cifs -o username=YourUserName,uid=$(id -u),gid=$(id -g) //SERVER/share ~/WinShare

在这里更改用户名、 SERVER 和 WinShare。这将询问您的 sudo 密码,然后它将询问远程共享的密码。

假设您在主文件夹中创建了 WinShare文件夹。运行此命令后,您应该能够看到 WinShare文件夹中的所有共享文件夹和文件。除此之外,由于您使用的是 uidgid标记,因此不必一直使用 sudo 就可以进行写访问。

  • 现在可以使用 -v标记运行容器,并在服务器和容器之间共享一个卷。

假设你是这样运行的。

docker run -d --name mycontainer -v /home/WinShare:/home 2d244422164

您现在应该能够访问 Windows 共享并从容器中修改它。

要测试它,只需要:

docker exec -it yourRunningContainer /bin/bash

cd /Home

touch testdocfromcontainer.txt

您应该在窗口共享中看到 testdocfromcontainer.txt