Docker在启动的时候,会根据Docker File 里的USER运行程序。
如果没有指定,会默认以ROOT进行启动。

注意到,在文件权限层面,docker 的用户、用户组是与宿主机相通的,虽然名字可能不一样,但共用一个userid。

如果深究原因,就要讨论到 linux 的空间隔离原理了,偏题太远。我们可以简单的这么理解:Linux的文件存储结构里,文件内容+文件属性(包括它的权限)是在一块儿的。docker产生的文件,“宿主机” 在同一操作系统的前提下,自然能无缝识别。

也就是说,docker默认的root,id是1,那么对应的就是宿主机的root(userid 也是 1)
如果 docker的默认用户是 new_user,id是1001,那么对应到的就是宿主机的 1001号用户,是哪位并不知道,不一定叫new_user。

假设是以ROOT启动的,那么在程序运行的过程中,我们挂载盘符之后,产生的一些中间文件的权限在宿主机看来就是id为1的用户的,也就是本机的ROOT的。

而一般我们基本不可能直接用root来操作docker,这样产生的文件我们都是无权限操作的,显然不能接受。

有什么办法修改呢?

有。

只要在 docker run 时,使用 -u ${USER} 来绑定用户就好。这样docker容器内部,就会用这个用户来启动默认进程了。

不过这个指令的使用有一个误区,如果 ${USER} 使用的是用户名,而docker容器里并没有预先初始化好这个用户,就会出现用户找不到的情况:

docker: Error response from daemon: unable to find user publisher: no matching entries in passwd file.

这时候用 userid 就可以了。这样docker容器就不会去解析用户名,得到userid,再对文件进行操作。

总结一下:

如果是使用外部正在登录的用户来对docker进行操作,那么用 -u userid 来进行,比如:

docker run --user $(id -u) --name mongo mongo

光是这样其实还不够,最好带上组信息,这样权限才是100%还原启动者的。

docker run --user $(id -u):$(id -g) --name mongo mongo

如果是使用特定的、docker容器里面的角色(比如jenkins),那么用 -u username 来进行,比如:

docker run --user ${DOCKER_USER} --name mongo mongo
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐