Docker - 可以将 NFS 共享挂载到容器中,但无法挂载其子目录

8

我有一个具有以下属性的NFS共享:

  • 在我的主机上挂载到路径/nfs/external_disk
  • 拥有者用户是test_user,其UID1234
  • 组是test_group,其GID2222
  • 权限为750

我有一个小的Dockerfile文件,其中包含以下内容

ARG tag=lts
from jenkins/jenkins:${tag}

user root

# Create a new user and new group that matches what is on the host.
ARG username=test_user
ARG groupname=test_group
ARG uid=1234
ARG gid=2222
RUN groupadd -g ${gid} ${groupname} && \
    mkdir -p /users && \
    useradd -l -m -u ${uid} -g ${groupname} -s /bin/bash -d /users/${username} ${username}

user ${username}

构建镜像后(名称为 custom_jenkins),运行以下命令,容器将被正确启动,并且可以看到原始的 Jenkins 主目录现在已经复制到了共享目录中。 ``` docker run -td --rm -v /nfs/external_disk:/var/jenkins_home custom_jenkins ```
但是,如果要挂载 NFS 共享的子目录,比如 `${NFS_SHARE}/jenkins_home`,就会出现错误: ``` docker run -td --rm -v /nfs/external_disk/jenkins_home:/var/jenkins_home custom_jenkins ```
错误信息如下: ``` docker: Error response from daemon: error while creating mount source path '/nfs/external_disk/jenkins_home': mkdir /nfs/external_disk/jenkins_home: permission denied. ```
即使我提前创建了这个子目录并将其权限设置为 777,也无济于事。请注意,我正在以具有与容器中相同 UID/GID 的 test_user 身份运行,实际上它拥有 NFS 共享。
我感觉当 Docker 尝试创建一个子目录时,它会尝试将其创建为某个不同的用户(例如“docker”用户),这会导致在共享内部无法访问而创建文件夹失败。
请问有人能提供帮助吗?非常感谢。

你能否尝试在docker run命令中添加--user <宿主操作系统中NFS所有者的UID>? 我有一个猜测,但请确认是否有效 ;) docker run -td --rm --user 1234 -v /nfs/external_disk/jenkins_home:/var/jenkins_home custom_jenkins - Neo Anderson
1
嗨,Neo,我不能代表O.P.发言,但我有一个类似的情况,我们为拥有NFS目录的用户包括“--user”。我得到了与O.P.相同的错误。这是你的意思吗?请注意,“root”无法访问此目录。我尝试过:docker run --rm -it -v <nfs_path_that_root_cannot_access>:<path_in_container> --user <id>:<gid> ubuntu /bin/bash - austinMLB
嘿@austinMLB,我尝试复制一下,但所有的都没问题。也许我还缺少你拥有的某些限制条件。我将在答案中描述我执行的步骤,以获得更好的格式。 - Neo Anderson
1
我最终挂载了整个共享目录,并在容器内创建了一个符号链接。 - user3396919
1
@user3396919 您可以添加您使用的详细命令,并甚至接受您自己的答案。这将有助于其他人。 - VonC
1个回答

2
我尝试复制了一下。对我来说完全没有问题。也许我错过了某些限制。无论如何,希望这可以帮到你。请注意,在第6步中,我创建的文件所属的所有者和组。这可能回答了你的一个问题。 步骤1:我在我的局域网某处创建了一个NFS共享。
步骤2:我挂载了该共享到运行docker引擎的机器上。
sudo mount 192.168.0.xxx:/i-data/b4024d5b/nfs/NFS /mnt/nsa320/

neo@neo-desktop:nsa320$ mount | grep NFS
192.168.0.xxx:/i-data/b4024d5b/nfs/NFS on /mnt/nsa320 type nfs (rw,relatime,vers=3,rsize=32768,wsize=32768,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.0.xxx,mountvers=3,mountport=3775,mountproto=udp,local_lock=none,addr=192.168.0.xxx)

步骤三:我创建了一些示例文件和一个子目录:

neo@neo-desktop:nsa320$ ls -la /mnt/nsa320/
total 12
drwxrwxrwx 3 root root 4096 Jul 21 22:54 .
drwxr-xr-x 3 root root 4096 Jul 21 22:41 ..
-rw-r--r-- 1 neo  neo     0 Jul 21 22:45 dummyFile
-rw-r--r-- 1 root root    0 Jul 21 22:53 fileCreatedFromContainer << THIS WAS CREATED FROM A CONTAINER THAT WAS NOT LAUNCHED WITH THE --user OPTION
drwxr-xr-x 2 neo  neo  4096 Jul 21 22:54 subfolder

步骤四:启动一个虚拟容器并挂载子目录(1000是我的操作系统中用户neo的UID):

docker run -d -v /mnt/nsa320/subfolder:/var/externalMount --user 1000 alpine tail -f /dev/null

步骤5: 在容器中连接以检查挂载情况(我可以读写位于NFS上的子文件夹)

neo@neo-desktop:nsa320$ docker exec -ti ded1dc79773e sh
/ $ ls /var/externalMount/
fileInSubfolder
/ $ touch /var/externalMount/fileInSubfolderCreatedFromContainer

步骤6: 回到主机,从容器中创建的文件属于谁:

neo@neo-desktop:nsa320$ ls -la /mnt/nsa320/subfolder/
total 8
drwxr-xr-x 2 neo  neo  4096 Jul 21 23:23 .
drwxrwxrwx 3 root root 4096 Jul 21 22:54 ..
-rw-r--r-- 1 neo  neo     0 Jul 21 22:54 fileInSubfolder
-rw-r--r-- 1 neo  root    0 Jul 21 23:23 fileInSubfolderCreatedFromContainer

可能与主题无关: 在容器中执行whoami仅返回UID:

$ whoami
whoami: unknown uid 1000

1
嗨,Neo,感谢你尝试复现这个问题。我要注意的是,在我们的情况下,“root”没有访问子文件夹的权限。我对NFS不够熟悉,不知道“root squash”的细节。基于此和我们看到的权限错误,我猜测Docker在某个时候是“root”或其他本地帐户实际进行挂载的。也就是说,我的“--user <id>”中的用户可以访问NFS目录,因此如果只有该用户在使用,我不明白为什么会出现权限错误。我不确定“root squash”是否是我们设置与您设置之间的区别。 - austinMLB
嗨@austinMLB,我同意你的评论 - root squash可能是唯一的区别。我也不是NAS专家,只是一个开发者,但也许你可以访问你的NAS来查看它在服务器端如何配置。这里有一些有趣的文档,在“用户ID映射”下 - https://linux.die.net/man/5/exports。我敢打赌,这个配置可能是解决这个问题的关键。祝好运,感谢你的回复和反馈! - Neo Anderson
Docker 以 root 用户启动,并将 NFS 共享挂载到容器中。你的 /mnt/nsa320/ 具有 777 权限,这意味着 root 用户也可以访问。然后容器会继续使用指定的 --user。如果你的 NFS 子文件夹权限为 <772,则无法实现这一点。 - Mihai Galos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接