容器内外的 Docker 用户:什么是对应关系(UID/GID),看到我不明白的效果

  • 本文关键字:GID UID 明白 关系 Docker 用户 docker
  • 更新时间 :
  • 英文 :


我试图很好地理解Docker的功能,以使我可以安全地使用它。对此的一种建议是始终在Dockerfile中使用USER语句。在尝试理解这一点的效果时,我遇到了一些麻烦。

具体问题:

  1. 哪种机制允许主机内核与仅存在于容器中的用户打交道?
  2. 为什么下面的Run2显示该目录属于testuser,但在目录中不允许ls
  3. 为什么下面的Run3显示该目录属于testuser

此问题底部的版本信息。

设置

我有以下dockerfile

FROM alpine@sha256:1354db23ff5478120c980eca1611a51c9f2b88b61f24283ee8200bf9a54f2e5c
LABEL version 2.0
LABEL description "Test image for setting user"
RUN adduser -D testuser1   ## sometimes removed
RUN adduser -D testuser2   ## sometimes removed
RUN adduser -D testuser
USER testuser
CMD sh

我用

构建它
docker build -t kasterma/testuser:1 .

然后用

运行
docker run -ti -v /home/kasterma/test-user/:/test-home kasterma/testuser:1

目录/home/kasterma/test-user/是包含Dockerfile的目录。

运行1:在Dockerfile中删除两行标记##sometimes removed

[root@datalocal01 test-user]# docker run -ti -v /home/kasterma/test-user/:/test-home kasterma/testuser:1
/ $ ls -lh
...
drwx------    2 1001     1001          40 Dec 30 14:08 test-home
...

此处显示用户,组都为1001;这是主机中kasterma的用户和groupID。在这种情况下,testuser具有UID和GID 1000。

/ $ cd test-home
sh: cd: can't cd to test-home

运行2:仅删除dockerfile中标记##sometimes removed的第二行。

/ $ ls -lh
...
drwx------    2 testuser testuser      40 Dec 30 14:12 test-home
...

/ $ cd test-home
/test-home $ ls
ls: can't open '.': Permission denied

现在testuserkasterma具有相同的UID和GID(尽管一个将它们放在容器中,而另一个则在主机中)。为什么我可以cd,而不能ls

运行3:在Dockerfile中删除两行标记##sometimes removed

/ $ ls -lh
...
drwx------    2 testuser testuser      40 Dec 30 14:15 test-home
...

/ $ cd test-home
sh: cd: can't cd to test-home

现在testuser具有UID和GID 1002,因此与kasterma不同。但是清单显示为testuser,但cd命令失败。

版本信息

OS版本(在VirtualBox中在VM上运行)

[root@datalocal01 test-user]# uname -a
Linux datalocal01 3.10.0-514.2.2.el7.x86_64 #1 SMP Tue Dec 6 23:06:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

和docker

[root@datalocal01 test-user]# docker version
Client:
 Version:         1.10.3
 API version:     1.22
 Package version: docker-common-1.10.3-59.el7.centos.x86_64
 Go version:      go1.6.3
 Git commit:      3999ccb-unsupported
 Built:           Thu Dec 15 17:24:43 2016
 OS/Arch:         linux/amd64
Server:
 Version:         1.10.3
 API version:     1.22
 Package version: docker-common-1.10.3-59.el7.centos.x86_64
 Go version:      go1.6.3
 Git commit:      3999ccb-unsupported
 Built:           Thu Dec 15 17:24:43 2016
 OS/Arch:         linux/amd64

当主机运行SELINUX时,如果没有标记,则可能无法访问文件系统内容。来自 MAN DOCKER-RUN

Selinux之类的标签系统要求将适当的标签放在 音量内容安装在容器中。没有标签,安全性 系统可能会阻止容器内部运行的过程 使用内容。默认情况下,Docker不会更改标签设置 由OS。要在容器上下文中更改标签,您可以添加 两个后缀之一:z或:z到音量安装座。这些后缀 告诉Docker在共享卷上重新标记文件对象。Z 选项告诉Docker两个容器共享卷内容。作为一个 结果,Docker用共享内容标签标记内容。共享 音量标签允许所有容器读取/写入内容。Z 选项告诉Docker将内容标记为私人unshared 标签。只有当前的容器才能使用私有卷。

所以,您可以尝试

而不是禁用Selinux
docker run -ti -v /home/kasterma/test-user/:/test-home:Z kasterma/testuser:1

请参阅与Docker一起使用卷,可能会引起Selinux的问题以获取更多详细信息。

我在盒子上尝试了您的用例(没有Selinux并拥有Docker版本1.12.5):我始终获得正确的" Testuser"所有权,我可以更改目录并列出其内容(我的本地UID是1000而且我没有更多用户)。因此,您的问题可能是由于较旧的Docker版本。

如果与selinux无关

检查主机的内核是否启用了用户名称空间(CentOS 7,这似乎是您正在使用的发行版,默认情况下不会启用它。

查看使用Docker上的用户名称空间,该空间描述了如何在CentOS 7上启用用户名称空间以及如何检查正确的行为。

关于用户名称空间的详细信息,查看以下几个站点:

Docker Engine中用户名称空间简介

Docker Security

用户名称空间已到达Docker!

用于您的用户的Docker-介绍用户名称空间

您可以在deni bertovic博客中引入用户名称空间之前(在Docker 1.10之前)中的Docker卷中的权限清晰说明 - 使用Docker卷处理权限。

希望它有帮助。

最新更新