如何在Docker容器中生成与主机用户具有相同所有者的文件
我使用docker容器在git仓库中完成一些开发任务。
我使用的容器是专门为每个项目构build的,每个贡献者只需要docker CLI即可完成任务。
糟糕的一面是容器以root身份运行,一旦容器停止,生成的文件就被root所拥有,这很糟糕。
在退出之前,我不能更改容器中的所有者,因为容器/ etc / passwd文件中没有所需的用户。
我会在编译docker镜像之前在容器中创build一个用户,但是这个容器不会是通用的(对于我的所有开发团队来说)。
最好的做法是什么?
一个解决scheme是在存储库中创build一个新的dockerfile
,该dockerfile
基于前一个映像(预先安装了devtools,但没有用户创build但是是root)。
在这样的dockerfile
,写下如下所示:
FROM <ABSTRACT_FORMER_IMAGE> ARG username=developer RUN useradd -r -u 1001 -g $username $username USER $username
然后,在开始工作之前,团队中的每个开发人员都应该使用dockerfile为新的项目+开发人员指定的容器构build自己的基础映像,并传递其用户名。
$ docker build --build-arg username=$USER Dockerfile
那里有一些更好的做法?
我build议你阅读这个链接,以便对Docker特权有完整的理解 – 对于你来说,解决scheme是使用–user命令运行docker。
您可以将用户添加到映像中,以root用户身份启动容器,并使用入口点调整容器内的uid / gid以匹配来自开发者的卷装载。 然后切换到您的容器用户运行您的应用程序。
为了实现这个,我使用了包含以下几行的入口点shell脚本:
OLD_UID=`getent passwd "${opt_u}" | cut -f3 -d:` NEW_UID=`ls -nd "$1" | cut -f3 -d' '` if [ "$OLD_UID" != "$NEW_UID" ]; then usermod -u "$NEW_UID" "$opt_u" if [ -n "$opt_r" ]; then find / -mount -uid "$OLD_UID" -exec chown "$opt_u" {} \; fi fi OLD_GID=`getent group "${opt_g}" | cut -f3 -d:` NEW_GID=`ls -nd "$1" | cut -f4 -d' '` if [ "$OLD_GID" != "$NEW_GID" ]; then groupmod -g "$NEW_GID" "$opt_g" if [ -n "$opt_r" ]; then find / -mount -gid "$OLD_GID" -exec chgrp "$opt_g" {} \; fi fi
在该脚本中, $1
是卷装入path, opt_u
是容器内的用户名, opt_g
是组名, opt_r
是recursion调整容器内文件系统的标志。
在我入境的最后,我开始了:
exec gosu "${RUN_AS}" "$@"
其中切换到用户$RUN_AS
和exec的命令作为该用户传递到入口点,并作为pid 1. Gosu用于避免su
作为pid 1运行。
我已经发布了一个与Jenkins类似的例子,作为容器内的应用程序来匹配docker套接字的GID。 你可以在这里find所有步骤的回购: https : //github.com/bmitch3020/jenkins-docker
这对于将图像移植到任何开发人员系统具有重大的优势,并且可以使用相同的命令来运行它。 无论文件系统上的权限是什么,它们从外部映射到容器中都成为在容器内运行命令的用户的uid / gid。 无需在开发者系统上查找docker run
命令的本地uid / gid,或者在每个开发人员工作站上使用唯一的uid / gid条目构build映像。 这个实现唯一的缺点是docker exec
会以root的身份进入容器,因为你需要以root的身份运行你的入口来修改用户/组和文件系统的所有权。