如何在 docker 容器中生成与主机用户具有相同所有者的文件

How to generate files in a docker container for having the same owner as the host's user

我使用 docker 容器在我的 git 存储库中完成一些开发任务。

我使用的容器是专门为每个项目构建的,这样每个贡献者只需要 docker CLI 就可以完成工作。

不利的一面是容器 运行 作为 root,因此一旦容器停止,生成的文件归 root 所有,这很糟糕..

我无法在退出前更改容器中的所有者,因为容器 /etc/passwd 文件中没有所需的用户。

我会在编译 docker 图像之前在容器中创建一个用户,但是容器不会通用(对于我的所有开发团队)。

最佳做法是什么?

一个解决方案是在存储库中创建一个新的 dockerfile,它基于以前的图像(预安装了 devtools 但没有创建用户,只有 root)。

在这样的dockerfile中,写下如下内容:

FROM <ABSTRACT_FORMER_IMAGE>
ARG username=developer
RUN useradd -r -u 1001 -g $username $username
USER $username

然后,在开始工作之前,团队中的每个开发人员都应该使用 dockerfile 为新项目+开发人员特定的容器构建自己的基础映像,并传递其用户名。

$ docker build --build-arg username=$USER Dockerfile

有哪些更好的做法?

我建议您阅读此 link 以全面了解 docker privileges - 对您来说,解决方案是 运行 docker 使用 - -用户命令。

您可以将您的用户添加到映像中,以 root 用户身份启动容器,并使用入口点调整容器内的 uid/gid 以匹配您的开发人员安装的卷。然后切换到您的容器用户 运行 您的应用程序。

为了实现这一点,我使用了一个入口点 shell 脚本,其中包含以下几行:

  OLD_UID=`getent passwd "${opt_u}" | cut -f3 -d:`
  NEW_UID=`ls -nd "" | 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 "" | 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

在该脚本中,</code>是卷挂载路径,<code>opt_u是容器内的用户名,opt_g是组名,opt_r是标记以递归调整容器内的文件系统。

在入口点的最后,我开始:

exec gosu "${RUN_AS}" "$@"

切换到用户 $RUN_AS 并执行作为该用户和 pid 1 传递到入口点的命令。Gosu 用于避免 su 运行 宁作为 pid 1.

我之前发布了一个类似的例子,使用 Jenkins 作为容器内的应用程序来匹配 docker 套接字的 GID。您可以在此处找到包含所有步骤的回购协议:https://github.com/bmitch3020/jenkins-docker

这具有使图像可移植到任何开发人员系统的显着优势,并且他们可以 运行 使用相同的命令。无论文件系统上的权限是什么,它们从外部映射到容器中都会成为容器内用户 运行ning 命令的 uid/gid。无需为您的 docker run 命令在开发人员系统上查找本地 uid/gid,或在每个具有唯一 uid/gid 条目的开发人员工作站上构建您的图像。此实现的唯一缺点是 docker exec 将以根用户身份进入容器,因为您需要 运行 您的入口点作为根用户才能访问修改 users/groups 和文件系统所有权。