Docker用户进出容器:什么是通信(UID / GID),看不到效果

我想了解docker的运行情况,以确保我能够安全地使用它。 一个build议是在Dockerfile中总是使用USER语句。 为了理解这个效果,我遇到了一些麻烦。

具体问题:

  1. 什么机制允许主机内核处理只存在于容器中的用户?
  2. 为什么下面的run2显示目录属于testuser但不允许ls在目录中?
  3. 为什么下面的run3显示属于testuser的目录?

版本信息在这个问题的底部。

build立

我有以下的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 

我用这个来构build它

 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:删除标记为“ ##sometimes removed在Dockerfile中删除”的两行。

 [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:只删除标记为##sometimes removed的第二行, ##sometimes removed在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(尽pipe它们在容器中,另一个在主机上)。 为什么我可以cd ,但不是ls

运行3:删除在Dockerfile中##sometimes removed标记为“ ##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命令失败。

版本信息

操作系统版本(在VirtualBox中的虚拟机上运行)

 [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时,如果文件系统没有标记,则可能无法访问文件系统内容。 从男子docker运行

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

所以,而不是禁用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既不是旧的Docker版本,你描述的行为似乎与用户命名空间有关

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

在Docker上使用User Namespaces来描述如何在CentOS 7上启用User namespaces,以及如何检查正确的行为。

关于用户命名空间的详细信息,看看几个网站,如:

Docker引擎中的用户命名空间简介

Docker安全

用户命名空间已经到达Docker!

你的用户的Docker – 引入用户命名空间

在Deni Bertovic博客介绍User Namespaces(在Docker 1.10之前)之前,您可以在Docker卷中find有关权限的明确说明- 处理Docker卷的权限 。

希望能帮助到你。