docker 容器是一种特殊的进程,namespace是一种隔离技术,docker就是使用隔离技术开启特定的namespace创建出一些特殊的进程-----容器
默认情况下,docker不会开启user namespace,所以说容器没有对user namespace进行隔离。
如何在docker中开启用户隔离功能
- 在/etc/docker/daemon.json中加入配置
userns-remap=default
如何没有daemon.json这个文件,需要自己创建。
$ vim /etc/docker/daemon.json
{
"userns-remap": "default"
}
- 重启docker
$ systemctl restart docker
验证用户隔离功能开启成功
- 首先docker创建了一个新的用户。
$ id dockremap
uid=114(dockremap) gid=121(dockremap) groups=121(dockremap)
- 查看对应的ID
$ cat /etc/subuid
dockremap:231072:65536
$ cat /etc/subgid
dockremap:231072:65536
UID从231072开始,可以使用的UID共有65535个,即使用范围是231072-(231072+65535)。
- 在/var/lib/docker目录下会创建一个以起始UID和GID命名的文件。
231072是dockremap用户映射出来的ID,这个文件包含了docker创建容器的所有的内容,并且对某些目录进行了权限限制。
$ ll /var/lib/docker/231072.231072/
total 0
drwx------ 14 231072 231072 182 Mar 27 01:45 ./
drwx--x--x 16 root root 221 Mar 27 01:44 ../
drwx------ 2 root root 24 Mar 27 01:40 builder/
drwx------ 4 root root 92 Mar 27 01:40 buildkit/
drwx------ 2 231072 231072 6 Mar 27 01:42 containers/
drwx------ 3 root root 22 Mar 27 01:40 image/
drwxr-x--- 3 root root 19 Mar 27 01:40 network/
drwx------ 7 231072 231072 328 Mar 27 01:45 overlay2/
drwx------ 4 root root 32 Mar 27 01:40 plugins/
drwx------ 2 root root 6 Mar 27 01:45 runtimes/
drwx------ 2 root root 6 Mar 27 01:40 swarm/
drwx------ 2 231072 231072 6 Mar 27 01:45 tmp/
drwx------ 2 root root 6 Mar 27 01:40 trust/
drwx------ 2 231072 231072 25 Mar 27 01:40 volumes/
创建容器
开启user namespace后,容器中的user ID会产生什么变化呢?与宿主机中的ID又是如何对应的呢?
$ docker run -d --name test ubuntu sleep infinity
$ ps aux | grep sleep
231072 26063 0.5 0.0 4532 788 ? Ss 01:48 0:00 sleep infinity
root 26121 0.0 0.0 14196 904 pts/0 S+ 01:48 0:00 grep --color=auto sleep
231072是用户dockremap的一个从属ID,在主机上是一个普通的用户,接下来我们进入到容器中:
$ docker exec -it 26e0ef1bc51a sh
$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4532 788 ? Ss 08:48 0:00 sleep infinity
root 7 0.6 0.0 4628 884 pts/0 Ss 08:52 0:00 sh
root 12 0.0 0.0 34400 2824 pts/0 R+ 08:52 0:00 ps aux
$ id root
uid=0(root) gid=0(root) groups=0(root)
可以看到容器中的sleep进程的user是root,即在容器中进程是以root用户启动的。
虽然是以root启动的,但是容器内的root用户是通过主机上的ID为231072映射过来的,实际上它只有有限的权限,但是仍然以root用户在容器内运行。
- 对volume的访问权限、
创建一个属于普通用户的volume,挂载到容器中
$ useradd etcd
$ id etcd
uid=1001(etcd) gid=1001(etcd) groups=1001(etcd)
chown -R etcd:etcd /tmp/data
$ ll /tmp/data
total 4
drwxr-xr-x 2 etcd etcd 22 Mar 27 02:07 ./
drwxrwxrwt 8 root root 144 Mar 27 02:07 ../
-rw-r--r-- 1 etcd etcd 5 Mar 27 02:02 rootfile
$ docker run -d -v /tmp/data:/data --name test ubuntu sleep infinity
$ docker exec -it 58a42529e9dea4f67119fa324602611c77cc66e092f12c77995409ad820108dd sh
$ ls -l
total 4
-rw-r--r-- 1 nobody nogroup 5 Mar 27 09:02 rootfile
$ cat rootfile
root
可见普通用户权限的文件挂载到容器中,对应的文件ownership变成了nobody,nogroup,并且都具有访问权限,经测试,root权限的ownership,在容器中也是可以访问的。
如何屏蔽用户空间隔离功能
在daemon.json中配置user-remap
是默认为所有的容器开启用户隔离,如果想为某个容器disable这个功能,如下:
$ docker run -d --userns=host --name sleepme ubuntu sleep infinity
$ ps aux | grep sleep
root 29312 0.1 0.0 4532 740 ? Ss 02:18 0:00 sleep infinity
root 29478 0.0 0.0 14196 976 pts/0 S+ 02:18 0:00 grep --color=auto sleep
此时,进程又归root所有了。
网友评论