运行 containerd 的 ctr 通过 uidmap 映射到主机上的非 root 用户的容器
run container with containerd's ctr by means of uidmap to map to non-root user on the host
为了更好地理解如何将 --uidmap
与 ctr
一起使用,我通过以下步骤创建了一个测试容器。 containerd
版本是 1.4.3
.
构建和运行容器:
- 构建 Dockerfile
$ cat Dockerfile
FROM alpine
ENTRYPOINT ["/bin/sh"]
和
$ docker build -t test .
Sending build context to Docker daemon 143.1MB
Step 1/2 : FROM alpine
---> d6e46aa2470d
Step 2/2 : ENTRYPOINT ["/bin/sh"]
---> Running in 560b09f9b287
Removing intermediate container 560b09f9b287
---> 8506bfeab109
Successfully built 8506bfeab109
Successfully tagged test:latest
- 将图像保存为 tar 球
$ docker save test > test.tar
- 使用 containerd 导入它
ctr
$ sudo ctr i import test.tar
unpacking docker.io/library/test:latest (sha256:9f7dabf0e4feadbca9bdc180422a3f2cdd7b545445180a3c23de8129dc95f29b)...done
- 创建并运行容器
$ sudo ctr run --uidmap 0:5000:4999 docker.io/library/test:latest test
uid 映射应将容器内部 uid 0(root)映射到对应于 ctr 的联机帮助页的 5000:
--uidmap="": run inside a user namespace with the specified UID mapping range; specified with the format container-uid:host-uid:length
检查容器和主机上的 UID:
容器内:
ps -eo ruser,rgroup,comm
RUSER RGROUP COMMAND
root root sh
root root ps
在主机上:
$ ps -eo uid,gid,cmd | grep /bin/sh
126 128 /bin/sh /usr/lib/lightdm/lightdm-greeter-session /usr/sbin/unity-greeter
0 0 /bin/sh
问题
它似乎不起作用,/bin/sh
运行在容器内和主机上作为 root (uid=0)。
我搜索了一段时间,直到我检查了 containerd 的代码并在 cmd/ctr/commands/run/run_unix.go
:
中找到了这个
149 if uidmap, gidmap := context.String("uidmap"), context.String("gidmap"); uidmap != "" && gidmap != "" {
150 uidMap, err := parseIDMapping(uidmap)
151 if err != nil {
152 return nil, err
153 }
154 gidMap, err := parseIDMapping(gidmap)
155 if err != nil {
156 return nil, err
157 }
这基本上意味着:
uidmap
AND gidmap
两者都必须提供,否则无法正常工作。
运行 上面的容器再次用
$ sudo ctr run --uidmap 0:5000:4999 --gidmap 0:5000:4999 docker.io/library/test:latest test
成功了。
容器内:
ps -eo ruser,rgroup,comm
RUSER RGROUP COMMAND
root root sh
root root ps
在主机上:
$ ps -eo uid,gid,cmd | grep /bin/sh
126 128 /bin/sh /usr/lib/lightdm/lightdm-greeter-session /usr/sbin/unity-greeter
5000 5000 /bin/sh
为了更好地理解如何将 --uidmap
与 ctr
一起使用,我通过以下步骤创建了一个测试容器。 containerd
版本是 1.4.3
.
构建和运行容器:
- 构建 Dockerfile
和$ cat Dockerfile FROM alpine ENTRYPOINT ["/bin/sh"]
$ docker build -t test . Sending build context to Docker daemon 143.1MB Step 1/2 : FROM alpine ---> d6e46aa2470d Step 2/2 : ENTRYPOINT ["/bin/sh"] ---> Running in 560b09f9b287 Removing intermediate container 560b09f9b287 ---> 8506bfeab109 Successfully built 8506bfeab109 Successfully tagged test:latest
- 将图像保存为 tar 球
$ docker save test > test.tar
- 使用 containerd 导入它
ctr
$ sudo ctr i import test.tar unpacking docker.io/library/test:latest (sha256:9f7dabf0e4feadbca9bdc180422a3f2cdd7b545445180a3c23de8129dc95f29b)...done
- 创建并运行容器
uid 映射应将容器内部 uid 0(root)映射到对应于 ctr 的联机帮助页的 5000:$ sudo ctr run --uidmap 0:5000:4999 docker.io/library/test:latest test
--uidmap="": run inside a user namespace with the specified UID mapping range; specified with the format container-uid:host-uid:length
检查容器和主机上的 UID:
容器内:
ps -eo ruser,rgroup,comm
RUSER RGROUP COMMAND
root root sh
root root ps
在主机上:
$ ps -eo uid,gid,cmd | grep /bin/sh
126 128 /bin/sh /usr/lib/lightdm/lightdm-greeter-session /usr/sbin/unity-greeter
0 0 /bin/sh
问题
它似乎不起作用,/bin/sh
运行在容器内和主机上作为 root (uid=0)。
我搜索了一段时间,直到我检查了 containerd 的代码并在 cmd/ctr/commands/run/run_unix.go
:
149 if uidmap, gidmap := context.String("uidmap"), context.String("gidmap"); uidmap != "" && gidmap != "" {
150 uidMap, err := parseIDMapping(uidmap)
151 if err != nil {
152 return nil, err
153 }
154 gidMap, err := parseIDMapping(gidmap)
155 if err != nil {
156 return nil, err
157 }
这基本上意味着:
uidmap
AND gidmap
两者都必须提供,否则无法正常工作。
运行 上面的容器再次用
$ sudo ctr run --uidmap 0:5000:4999 --gidmap 0:5000:4999 docker.io/library/test:latest test
成功了。
容器内:
ps -eo ruser,rgroup,comm
RUSER RGROUP COMMAND
root root sh
root root ps
在主机上:
$ ps -eo uid,gid,cmd | grep /bin/sh
126 128 /bin/sh /usr/lib/lightdm/lightdm-greeter-session /usr/sbin/unity-greeter
5000 5000 /bin/sh