发生了什么?
普通用户(在docker用户组中)通过docker创建了一个文件,结果显示该文件的所有者却是root,且该普通用户已无权删除该文件:

接着,我又使用root用户在宿主机直接创建一个文件:

然后切换回普通用户,再使用docker去删除该文件:

再回头看该文件:

发现该文件已经被删除了。
是不是有种细思极恐的感觉:普通用户只要通过docker就能以root权限执行命令。
为什么会这样?
两个原因直接导致了这种情况的发生:
- 对linux内核来说,它没有用户的概念,它只认uid和gid
例如root用户的uid=0,普通用户的uid可能为其他一些数字。这意味着同一个uid可以对应多个用户名 - docker容器默认就是使用root账户运行的
可以通过 cat /etc/passwd
命令查看所有的用户:

例如这里显示 root 用户的uid为0,gid为0,hunt 用户的uid和gid均为1000。
那该怎么办?
最简单的想法自然是让docker不以root用户运行了。docker本身就支持 -u
指令用来指定执行的用户。

可以看到使用 -u 命令指定了非root权限的uid后新创建的文件就不再是root用户的了。
所以,生产环境需要指定非root用户启动容器才比较安全。
关于指定的uid
但同时也能看到对于新启动的容器,它并不知道uid=1000到底是哪个用户。那为什么那个文件还是显示为hunt创建的呢?这是因为宿主机中恰好有个uid=1000的用户名为hunt,所以若我用另一个两边都没有的uid创建文件:

可以看到容器显示找不到该用户,宿主机也是直接使用uid来标识文件所有者。
已经使用root用户启动的容器怎么办?
已经启动的容器要想修改一些启动参数相对较为复杂,不过也不用过于担心,docker本身也考虑到这一点,所以它使用了 Linux Capabilities
机制。
使用docker执行命令的root用户和本机的root用户是同一个吗?
并不是,前面有提到,对内核来说它只认uid和gid,docker使用它的root用户(uid=0)创建了文件,在宿主机中因为uid=0的也是root用户,故在宿主机看来就像是同一个root用户创建的文件一样。
Linux Capabilities
linux中的进程分为特权进程(priviledged processes)和非特权进程(priviledged processes)。使用root权限启动的进程即为特权进程,这种进程拥有较多的权限。这里的root用户指的是uid=0的用户,其用户名不一定叫root。
事实上,linux对root用户的权限有进一步的细分,类似rbac权限管理模型。root用户的权限又细分为38个小权限,例如:CAP_CHOWN(修改文件所有者的权限)、CAP_SETGID(允许改变进程的 GID)、CAP_SYS_BOOT(允许重新启动系统)等。
上面说了,事实上docker容器的root用户和宿主机的root是不同的,不同点就在于它们拥有的这些小权限不同,docker容器的root只有其中的14项小权限。这也最大限度保证了宿主机系统的安全。
我就是想给容器超级权限,就是玩,该怎么办?
docker run --privileged=true ...
总结
启动容器时记得指定用户
参考
https://www.cnblogs.com/woshimrf/p/understand-docker-uid.html
https://www.cnblogs.com/shoufu/p/14454793.html