我将首先以 docker 组中的普通用户(marc)身份登陆服务器。这容许我在不使用 sudo 命令的状况下启动 docker 容器。而后,从容器外部,让咱们看看这个过程是如何出现的。linux
marc@server:~$ docker run -d ubuntu:latest sleep infinity92c57a8a4eda60678f049b906f99053cbe3bf68a7261f118e411dee173484d10marc@server:~$ ps aux | grep sleeproot 15638 0.1 0.0 4380 808 ? Ss 19:49 0:00 sleep infinity复制代码
有趣。即便我从未输入 sudo 而且我不是 root 用户,我执行的 sleep 命令也以root 用户身份启动并具备 root 权限。我怎么知道它有 root 权限?容器内的 root = =容器外的 root 吗?是的,由于正如我所提到的,有一个内核和一个共享的 uids 和 gids 池。由于用户名在容器外部显示为“root”,因此我能够确定地知道容器内的进程是由具备uid = 0的用户启动的。docker
当我在 Dockerfile 中建立不一样的用户并以该用户身份启动命令时会发生什么?为了简化这个例子,我没有在这里指定一个gid,但一样的概念适用于组ID.ubuntu
首先,我将这些命令做为用户“marc”运行,其 uid 为1001。安全
marc@server:~$ echo $UID1001复制代码
和 Dockerfile:bash
FROM ubuntu:latestRUN useradd -r -u 1001 -g appuser appuserUSER appuserENTRYPOINT [“sleep”, “infinity”]复制代码
让咱们构建并运行它:服务器
marc@server:~$ docker build -t test .Sending build context to Docker daemon 14.34 kBStep 1/4 : FROM ubuntu:latest — -> f49eec89601eStep 2/4 : RUN useradd -r -u 1001 appuser — -> Running in 8c4c0a442ace — -> 6a81547f335eRemoving intermediate container 8c4c0a442aceStep 3/4 : USER appuser — -> Running in acd9e30b4aba — -> fc1b765e227fRemoving intermediate container acd9e30b4abaStep 4/4 : ENTRYPOINT sleep infinity — -> Running in a5710a32a8ed — -> fd1e2ab0fb75Removing intermediate container a5710a32a8edSuccessfully built fd1e2ab0fb75marc@server:~$ docker run -d test8ad0cd43592e6c4314775392fb3149015adc25deb22e5e5ea07203ff53038073marc@server:~$ ps aux | grep sleepmarc 16507 0.3 0.0 4380 668 ? Ss 20:02 0:00 sleep infinitymarc@server:~$ docker exec -it 8ad0 /bin/bashappuser@8ad0cd43592e:/$ ps aux | grep sleepappuser 1 0.0 0.0 4380 668 ? Ss 20:02 0:00 sleep infinity复制代码
marc@server:~$ docker run -d --user 1001 ubuntu:latest sleep infinity84f436065c90ac5f59a2256e8a27237cf8d7849d18e39e5370c36f9554254e2bmarc@server$ ps aux | grep sleepmarc 17058 0.1 0.0 4380 664 ? Ss 21:23 0:00 sleep infinity复制代码
marc@server:~$ docker exec -it 84f43 /bin/bashI have no name!@84f436065c90:/$复制代码
须要注意的是,在建立容器时指定用户标志也会覆盖 Dockerfile 中的该值。还记得第二个例子,我使用的 Dockerfile 有一个映射到本地主机上不一样用户名的uid吗?当咱们在命令行上使用用户标志运行它以启动执行“睡眠无限”过程的容器时会发生什么?app
marc@server:$ docker run -d test489a236261a0620e287e434ed1b15503c844648544694e538264e69d534d0d65marc@server:~$ ps aux | grep sleepmarc 17689 0.2 0.0 4380 680 ? Ss 21:28 0:00 sleep infinitymarc@server:~$ docker run --user 0 -d testac27849fcbce066bad37190b5bf6a46cf526f56d889af61e7a02c3726438fa7amarc@server:~$ ps aux | grep sleepmarc 17689 0.0 0.0 4380 680 ? Ss 21:28 0:00 sleep infinityroot 17783 0.3 0.0 4380 668 ? Ss 21:28 0:00 sleep infinity复制代码
在上面的最后一个例子中,你能够看到我最终有2个容器运行睡眠过程,一个用做“marc”,另外一个用做“root”。这是由于第二个命令经过--user 在命令行上传递标志来更改uid.
工具
一、若是已知的 uid 表示容器内的进程正在执行,则可能就像限制对主机系统的访问同样简单,以便容器中的 uid 有有限的访问权限。测试
二、更好的解决方案是使用已知的 uid 启动容器--user(您也可使用用户名,但请记住,它只是从主机的用户名系统提供uid的更友好的方式),而后限制对主机上的 uid 的访问你决定容器将运行为。ui
三、因为 uid 和用户名(以及gid和组名称)如何从容器映射到主机,所以指定容器化进程运行的用户可使进程看起来由内部和容器外部的不一样用户拥有。
- end -
做者:Marc Campbell
本文转载于外网,转载请标明出处