如何在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的身份运行你的入口来修改用户/组和文件系统的所有权。