用户ID的映射

13

我正在评估 rootless 模式下的 Podman,并遇到了用户 ID 映射的问题。

我使用 ID 为 1000 的 "myuser" 用户运行 Podman。

cat /etc/subuid
myuser:100000:65536

在运行一个以 root 为 pod 用户的 pod 时,挂载卷上创建的文件从主机的角度看属于 "myuser",我可以访问它们,所以一切正常。

当运行一个以非 root(例如 UID 2002)作为 pod 用户的 pod 时,在挂载卷上创建的文件从主机的角度看属于 UID "102002",这导致了这样的情况:我无法访问主机上的这些文件

如预期的那样,podman unshare 的效果如下所示。

podman unshare cat /proc/self/uid_map
0       1000          1
1     100000      65536

通过正确配置podman运行或配置文件,我有没有机会访问这些文件?

谢谢 Joerg


在容器中以UID 2002 运行创建文件通常会在宿主机上创建一个所有权为UID 102001 的文件,如果 /etc/subuid 包含 _myuser:100000:65536_。你是否在某种程度上使用了 --userns - Erik Sjölund
我在Ubuntu 20.05上遇到了一个相关问题,通过安装uidmap软件包进行了修复。 - Pablo Bianchi
3个回答

18

2022年11月4日更新

Podman 4.3.0 引入了选项 uidgid,可以应用于 --userns keep-id

此答案中描述的 UID 和 GID 映射现在可以改为使用 --userns keep-id:uid=$uid,gid=$gid。唯一的区别是新语法更加简洁,省去了一些打字。

请参考以下故障排除提示:

Podman 运行失败,显示错误消息 "Error: unrecognized namespace mode keep-id:uid=1000,gid=1000 passed"


是的,你可以使用命令行选项--uidmap来重新映射 UID。

看起来你正在使用的容器 UID 是

102002-100000+1=2003

数字1存在的原因是在容器中,默认情况下,主机上的普通UID被映射到容器中的root帐户。

该示例演示了此类计算(1002002-100000+1=2003)。

$ id  -un
testuser
$ grep testuser /etc/subuid
testuser:100000:65536
$ grep testuser /etc/subgid
testuser:100000:65536
$ mkdir dir1
$ chmod 777 dir1
$ podman run --rm -v ./dir1:/dir1:Z \
             --user 2003:2003 \
             docker.io/library/ubuntu touch /dir1/a
$ ls -l dir1/a
-rw-r--r--. 1 102002 102002 0 Jan 19 19:35 dir1/a
$

让我们定义一些变量,以便这个 Stackoverflow 的答案能够更具可重用性。

uid=2003
subuidStart=100000
subuidSize=65536

你可以尝试同时使用以下三个选项来运行podman
  • --uidmap $uid:0:1
  • --uidmap 0:1:$uid
  • --uidmap $(($uid+1)):$(($uid+1)):$(($subuidSize-$uid))

请注意$(( expression ))是Bash语法,因此您需要使用Bash shell。

--uidmap $uid:0:1

将容器中的UID $uid 映射到主机上的普通UID。

主机UID 中间UID 容器UID
普通主机UID 0 $uid

--uidmap 0:1:$uid

将容器内UID在0$uid-1之间的UID映射到子UID的较低部分(从$subuidStart$subuidStart+$uid-1)。

主机UID 中间UID 容器UID
$subuidStart 1 0
$subuidStart + 1 2 1
... ... ...
$subuidStart+$uid-1 $uid $uid-1

--uidmap $(($uid+1)):$(($uid+1)):$(($subuidSize-$uid))

将容器内UID在$uid+1$subuidSize之间的UID映射到其余子UID。

主机UID 中间UID 容器UID
$subuidStart + $uid $uid + 1 $uid + 1
$subuidStart + $uid + 1 $uid + 2 $uid + 2
... ... ...
$subuidStart + $subuidSize - 1 $subuidSize $subuidSize

请注意,主机UID和中间UID之间的映射不能由用户修改。普通主机UID始终映射到中间UID 0

请注意,一般情况下可能存在多个子UID范围。

有一个类似的命令行选项--gidmap用于GID。

更新于2022-02-14

我在Podman文档中写了一个故障排除提示


1
我已经使用--uidmap逻辑创建了一个脚本。我收到了错误信息“Error: Container ID 0 cannot be mapped to a host ID”,因此我添加了“--uidmap=0:1:1”作为附加参数。现在我收到以下错误信息: - Jörg Lang
你知道是否可以对 podman build 做同样的操作吗?我尝试将 --uidmap 替换为 --userns-uid-map,但似乎没有任何作用。 - Cezary Drożak
1
我从未尝试过使用--userns-uid-map来进行podman build,但我猜想它会执行和podman run中的--uidmap相同的操作。 - Erik Sjölund
我有同样的问题。对于podman run,选项很清楚,但是我无法弄清楚containerUID可能是一个有效的值,因为将为镜像的构建创建一个新的容器。我是不是漏掉了什么? - undefined

2

0
正如用户muzammil已经指出的那样,使用选项--userns=keep-id是解决这个问题的一种简单有效的方法。
假设容器内有一个需要访问挂载卷的用户999,那么您可能希望使用以下选项运行podman:
--userns=keep-id:uid=999

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