首页 >后端开发 >C++ >使用 docker_userid_fixer 修复 docker 容器中的用户 ID 的优雅方法

使用 docker_userid_fixer 修复 docker 容器中的用户 ID 的优雅方法

王林
王林原创
2024-08-15 18:42:02642浏览

an elegant way to fix user IDs in docker containers using docker_userid_fixer

这是关于什么的?

这是一个使用 docker 容器与 docker 主机交互的相当技术性的问题,通常与使用容器内的主机文件系统有关。
这种情况尤其发生在可重复的研究背景下。
我开发了一个开源实用程序来帮助解决这个问题。

docker 容器作为执行环境

docker 容器的初始和主要用例:一个独立的应用程序,仅通过某些网络端口与主机系统交互。
考虑一个 Web 应用程序:docker 容器通常包含一个 Web 服务器和一个 Web 应用程序,例如在端口 80(容器内部)上运行。然后,通过将容器内部端口 80 绑定到主机端口(例如 8000),容器在主机上运行。
那么容器化应用程序和主机系统之间的唯一交互就是通过这个绑定的网络端口。

容器作为执行环境是完全不同的:

  • 容器化的不是应用程序,而是应用程序构建系统
    • 它可以是编译器、IDE、笔记本引擎、Quarto 发布系统...
  • 目标是:
    • 拥有标准、易于安装和共享的环境
      • 想象一个复杂的构建环境,其中包含固定版本的 R、Python 和无数的外部包。 安装正确版本的所有内容可能是一项非常困难且耗时的任务。 通过共享包含已安装和预配置的所有内容的 docker 映像,可以真正节省时间。
    • 拥有一个可重现的环境
      • 通过使用它,您可以重现一些分析结果,因为您使用的是完全相同的受控环境
      • 您还可以轻松地重现错误,这是修复错误的第一步

但是,为了使用这些执行环境,这些容器必须有权访问主机系统,特别是主机用户文件系统。

docker 容器和主机文件系统

假设您已经容器化了一个 IDE,例如工作室。
您的 Rstudio 安装并在 docker 容器内运行,但它需要读取和编辑项目文件夹中的文件。

为此,您使用 docker run --volume 选项绑定挂载
您的项目文件夹(在主机文件系统中)。

然后您的文件就可以从 docker 容器中访问。

现在的挑战是文件权限。假设您的主机用户的用户 ID 1001,并假设在容器中拥有 Rsudio 进程的用户是 0(root)或 1002

如果容器用户是root
,那么它在读取你的文件时不会有任何问题。 但是,一旦您编辑一些现有文件,生成新文件(例如 pdf、html),这些文件将属于主机文件系统上的根
.

这意味着您的本地主机用户将无法使用它们或删除它们,因为它们属于 root。

现在,如果容器用户 ID 为 1002
,Rstudio 可能无法读取您的文件、编辑它们或生成新文件。

即使可以,通过设置一些非常宽松的权限,您的本地主机用户也可能无法使用它们。

当然,解决该问题的一种强力方法是在主机上和 docker 容器中都以 root 身份运行。这并不总是可行,并且会引发一些明显的关键安全问题。

解决文件所有者问题第 1 部分:docker run --user 选项

因为我们无法提前知道主机的用户ID(这里1001
),所以我们无法预先配置

docker 容器用户的 userid。

docker run 现在提供了一个 --user 选项,可以使用提供的用户 ID 创建一个

用户 在运行时。例如, docker run --user 1001 ... 将创建一个运行进程的 docker 容器 属于用户 ID 1001

.

的用户

那么我们还在讨论这个问题什么呢?没解决吗?

这里有一些关于动态创建的用户的怪癖:
  • 这是一个伪用户
  • 它没有主目录 (/home/xxx)
  • 它没有出现在/etc/passwd中
  • 它无法预先配置,例如使用 bash 配置文件、一些环境变量、应用程序默认值等...

我们可以解决这些问题,但这可能会很乏味且令人沮丧。
我们真正想要的是预先配置一个 docker 容器用户,并能够在 runtime... 动态更改他的 userid

解决文件所有者问题第2部分:输入docker_userid_fixer

docker_userid_fixer 是一个开源实用程序,旨在用作 docker 入口点 来修复我刚刚提出的用户 ID 问题。

让我们看看如何使用它:将其设置为 docker ENTRYPOINT,指定应使用哪个用户并动态修改他的 userid

ENTRYPOINT ["/usr/local/bin/docker_userid_fixer","user1"]

让我们准确地说:

  • 目标用户,是向docker_userid_fixer请求的用户,这里是user1
  • 请求的用户,是由docker run配置的用户,即(最初)拥有第一个进程(PID 1)的用户

然后,在容器运行时创建时,有两个选项:

  • 请求的用户ID(已经)与目标用户ID匹配,则无需更改
  • 或者没有。例如,请求的用户ID是1001目标用户ID是100。 然后,docker_userid_fixer 会直接在容器主进程中将 target 用户 user1 的 userid 从 1000 修复为 1001。

所以在实践中这解决了我们的问题:

  • 如果您不需要修复容器用户ID,只需使用通常的方式运行 docker run (不带 --user 选项)
  • 或者您使用 --user 选项,那么除了使用您请求的用户 ID 运行主进程之外,它还会将您的预配置用户修改为您请求的用户 ID,以便您的容器以您的预期用户和预期运行用户 ID。

docker_userid_fixer 设置

您可以在此处找到有关设置的说明。

但归结为:

  • 构建或下载小型可执行文件 (17k)

  • 将其复制到您的 Docker 镜像中

  • 使其作为 setuid root 可执行

  • 将其配置为您的入口点

血淋淋的细节

我写了一些简短的注释 https://github.com/kforner/docker_userid_fixer#how-it-works
但我会尝试改写。

实现的关键是容器中 docker_userid_fixer 可执行文件的 setuid root
我们需要 root 权限来更改 userid,并且此 setuid 只能为
启用特权执行 docker_userid_fixerprogram,并且持续很短的时间。

一旦需要修改userid,docker_userid_fixer就会切换主进程
发送给请求的用户(和用户 ID!)。

如果您对这些主题(docker、可重复研究、R 包开发、算法、性能优化、并行性...)感兴趣,请随时与我联系,讨论工作和商业机会。

以上是使用 docker_userid_fixer 修复 docker 容器中的用户 ID 的优雅方法的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn