Docker用户进出容器:什么是对应关系(UID/GID),看到我不理解的效果

kas*_*rma 5 docker

我正在努力了解docker的功能,以便我有理由相信我正在安全地使用它.对此的一个建议是始终USER在Dockerfile中使用语句.在试图了解这种效果时我遇到了一些麻烦.

具体问题:

  1. 什么机制允许主机内核处理仅存在于容器中的用户?
  2. 为什么下面的run2显示目录所属,testuser但不允许ls目录中的when?
  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
Run Code Online (Sandbox Code Playgroud)

我建立这个

docker build -t kasterma/testuser:1 .
Run Code Online (Sandbox Code Playgroud)

然后运行

docker run -ti -v /home/kasterma/test-user/:/test-home kasterma/testuser:1
Run Code Online (Sandbox Code Playgroud)

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

运行1:删除##sometimes removedDockerfile中标记的两行.

[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
...
Run Code Online (Sandbox Code Playgroud)

这里显示用户和组都是1001; 这是kasterma主机中的用户和groupid .在这种情况下testuser有uid和gid 1000.

/ $ cd test-home
sh: cd: can't cd to test-home
Run Code Online (Sandbox Code Playgroud)

运行2:仅删除##sometimes removedDockerfile中标记的第二行.

/ $ ls -lh
...
drwx------    2 testuser testuser      40 Dec 30 14:12 test-home
...
Run Code Online (Sandbox Code Playgroud)

/ $ cd test-home
/test-home $ ls
ls: can't open '.': Permission denied
Run Code Online (Sandbox Code Playgroud)

现在,testuserkasterma具有相同的UID和GID(虽然一个有他们在容器中,而其他主机上).我为什么可以cd,但不是ls吗?

运行3:不删除##sometimes removedDockerfile中标记的行.

/ $ ls -lh
...
drwx------    2 testuser testuser      40 Dec 30 14:15 test-home
...
Run Code Online (Sandbox Code Playgroud)

/ $ cd test-home
sh: cd: can't cd to test-home
Run Code Online (Sandbox Code Playgroud)

现在testuser有uid和gid 1002,所以不一样kasterma.但是列表显示它是testuser,但是cd命令失败了.

版本信息

操作系统版本(在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
Run Code Online (Sandbox Code Playgroud)

并为码头工人

[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
Run Code Online (Sandbox Code Playgroud)

gil*_*ile 5

当主机运行SELinux时,如果没有标记,则可能无法访问文件系统内容.从男子码头运行

像SELinux这样的贴标系统要求在安装到容器中的体积内容上放置适当的标签.如果没有标签,安全系统可能会阻止容器内运行的进程使用内容.默认情况下,Docker不会更改操作系统设置的标签.要更改容器上下文中的标签,可以在卷装入中添加两个后缀之一:z或:Z. 这些后缀告诉Docker重新标记共享卷上的文件对象.z选项告诉Docker两个容器共享卷内容.因此,Docker使用共享内容标签标记内容.共享卷标签允许所有容器读/写内容.Z选项告诉Docker使用私有非共享标签标记内容.只有当前容器才能使用私有卷.

所以,你可以试试,而不是禁用SELinux

docker run -ti -v /home/kasterma/test-user/:/test-home:Z kasterma/testuser:1
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅使用具有Docker的卷可能导致SELinux出现问题.

我在我的盒子上尝试了你的用例(没有SELinux和Docker版本1.12.5):我总是得到正确的"testuser"所有权,我能够更改目录并列出其内容(我的本地uid是1000,我的避风港)它上面有更多用户).所以,可能是你的问题是由于较旧的Docker版本.

如果既不与SELinux相关,也不与旧的Docker版本相关,那么您描述的行为似乎与用户名空间有关.

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

请参阅Docker上的使用用户命名空间,其中介绍了如何在CentOS 7上启用用户命名空间以及如何检查正确的行为.

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

Docker Engine中用户命名空间简介

Docker Security

用户名称空间已经到达Docker了!

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

Deni Bertovic博客上引入用户名空间(Docker 1.10之前)之前,您可以找到有关Docker卷中权限的清晰描述- 使用Docker卷处理权限.

希望能帮助到你.