我试图很好地理解Docker的功能,以使我可以安全地使用它。对此的一种建议是始终在Dockerfile中使用USER
语句。在尝试理解这一点的效果时,我遇到了一些麻烦。
具体问题:
- 哪种机制允许主机内核与仅存在于容器中的用户打交道?
- 为什么下面的Run2显示该目录属于
testuser
,但在目录中不允许ls
? - 为什么下面的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
现在testuser
和kasterma
具有相同的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 标签。只有当前的容器才能使用私有卷。
所以,您可以尝试
而不是禁用Selinuxdocker 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卷处理权限。
希望它有帮助。