Docker userns-remap无法写入已挂载目录

Dan*_*vic 6 namespaces docker

我正在尝试Docker 的userns-remap功能,以root用户身份在容器内创建一个文件,并test以主机上的用户身份拥有此文件的所有者。

我已将以下内容添加到 /etc/docker/daemon.json

{
  "userns-remap": "test:test"
}
Run Code Online (Sandbox Code Playgroud)

重新映射似乎是根据守护程序日志进行的

User namespaces: ID ranges will be mapped to subuid/subgid ranges of: test:test
Run Code Online (Sandbox Code Playgroud)

和条目test:100000:65536,并test:100000:65536已被添加到/etc/subuid/etc/subgid/分别文件。

但是当我启动一个容器并尝试在工作目录中创建文件时,它失败了

test@box:~$ docker run -v /home/test/tmp:/somedir -w /somedir -it ubuntu:16.04 /bin/bash
root@11ff6c42ffe1:/somedir# touch file.txt
touch: cannot touch 'file.txt': Permission denied

root@11ff6c42ffe1:/somedir# ls -l
total 0
-rw-rw-r-- 1 nobody nogroup 0 Mar 23 21:39 already_existing_file.txt

root@11ff6c42ffe1:/somedir# id root
uid=0(root) gid=0(root) groups=0(root)

root@11ff6c42ffe1:/somedir# touch /file.txt
Run Code Online (Sandbox Code Playgroud)

可以按预期在未从主机挂载的其他目录中创建文件。

另外,如果将777许可权授予安装的目录(在本例中为主机上的/ home / test / tmp),则可以从容器内部成功创建文件。但是,新创建的文件在主机上具有以下权限:

ls -l /home/test/tmp
total 0
-rw-r--r-- 1 165536 165536 0 march 29 01:36 file.txt 
Run Code Online (Sandbox Code Playgroud)

ID为165536的用户不存在于/ etc / passwd中,这使我们重新开始。我希望容器内的root用户具有与主机上的测试用户相同的权限,并且容器中的root用户创建的文件具有使用userns-remap映射的主机(即test)上的所有者。

文档中指出

...如果从主机挂载卷,则必须预先安排文件所有权,需要对卷内容进行读写访问。

...一个值得注意的限制是无法使用mknod命令。由root用户运行时,拒绝在容器内创建设备的权限。

这是否意味着即使安装目录的所有者是root用户使用userns-remap映射到的用户(在本例中为test),容器内的root用户也无法在安装目录内创建文件/目录?

有什么想法可以使用户也可以在容器内写入工作目录吗?


Docker版本:18.03.0
Ubuntu版本:16.04.1
内核版本:4.13.0-36-generic

重现步骤

sudo adduser test
sudo usermod -aG docker test
sudo echo '{ "userns-remap": "test"}' >> /etc/docker/daemon.json
service docker restart
su - test
mkdir tmp
docker run -v /home/test/tmp:/somedir ubuntu:16.04 touch /somedir/file.txt
Run Code Online (Sandbox Code Playgroud)

这是一些类似的问题,但并不完全相同,因为我想在修改Dockerfile的情况下完成这项工作:

小智 6

要回答您的问题,最好的方法是使用 docker 引擎的“用户命名空间”功能。

这是一个如何使用的示例。假设您的主机用户myuser具有 id3000

添加myuser:3000:65536到您的/etc/subuid/etc/subgid文件

用这个更新你的 /etc/docker/daemon.json :

{
  "userns-remap": "myuser"
} 
Run Code Online (Sandbox Code Playgroud)

不要忘记重新启动您的 docker 引擎 :)

就是这样,属于您的myuser本地帐户的所有文件都将属于0您的容器id是您的容器,反之亦然。

这应该可以帮助您解决问题。

让我知道