”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 使用 docker_userid_fixer 修复 docker 容器中的用户 ID 的优雅方法

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

发布于2024-11-01
浏览:444

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 选项

因为我们无法提前知道主机的userid是什么(这里1001),所以我们无法预先配置
docker容器用户的userid。

docker run 现在提供了一个 --user 选项,可以使用一些提供的 userid 创建一个 pseudo 用户
在运行时。例如, 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(不带--user选项)
  • 或者您使用 --user 选项,那么除了使用您请求的用户 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 包开发、算法、性能优化、并行性...)感兴趣,请随时与我联系,讨论工作和商业机会。

版本声明 本文转载于:https://dev.to/kforner/an-elegant-way-to-fix-user-ids-in-docker-containers-using-dockeruseridfixer-3c9i如有侵犯,请联系[email protected]删除
最新教程 更多>
  • Slim 和 Flight PHP 框架比较
    Slim 和 Flight PHP 框架比较
    为什么要使用微框架? 在社交媒体上,新的 PHP 开发人员经常会问“我的项目应该使用什么框架”,通常给出的答案是“Laravel”或“Symfony”。 虽然这些都是不错的选择,但这个问题的正确答案应该是“你需要框架做什么?” 正确的框架应该能够满足您的需要,并且不会包含大量您永远...
    编程 发布于2024-11-07
  • 如何构建您的第一个 Python 游戏:使用 PyGame 创建简单射击游戏的分步指南
    如何构建您的第一个 Python 游戏:使用 PyGame 创建简单射击游戏的分步指南
    Hi lovely readers, Have you ever wanted to create your own video game? Maybe you’ve thought about building a simple shooter game where you can move ar...
    编程 发布于2024-11-07
  • 为什么我的 Java JDBC 代码在连接到 Oracle 时抛出“IO 错误:网络适配器无法建立连接”?
    为什么我的 Java JDBC 代码在连接到 Oracle 时抛出“IO 错误:网络适配器无法建立连接”?
    诊断 Oracle JDBC“IO 错误:网络适配器无法建立连接”尝试使用 JDBC 执行简单的 Java 代码时要连接到 Oracle 数据库,您可能会遇到神秘的错误“IO 错误:网络适配器无法建立连接”。这个令人费解的消息源于 JDBC 驱动程序的模糊术语,并且可能由各种根本原因造成。以下是一些...
    编程 发布于2024-11-07
  • 如何使用 SwingPropertyChangeSupport 动态更新 JTextArea?
    如何使用 SwingPropertyChangeSupport 动态更新 JTextArea?
    使用 SwingPropertyChangeSupport 动态更新 JTextArea在此代码中,每当底层数据模型表示时,SwingPropertyChangeSupport 用于触发 JTextArea 中的更新通过 ArrayForUpdating 类进行更改。这允许动态更新 GUI 以响应数...
    编程 发布于2024-11-07
  • 如何将 Bootstrap 列中的内容居中?
    如何将 Bootstrap 列中的内容居中?
    Bootstrap 列中内容居中在 Bootstrap 中,可以通过多种方法实现列中内容居中。一常见的方法是在列 div 中使用align=“center”属性。例如:<div class="row"> <div class="col-xs-1&q...
    编程 发布于2024-11-07
  • 使用 Golang 进行身份验证、授权、MFA 等
    使用 Golang 进行身份验证、授权、MFA 等
    "Ó o cara falando de autenticação em pleno 2024!" Sim! Vamos explorar como realizar fluxos de autenticação e autorização, e de quebra, entender a dife...
    编程 发布于2024-11-07
  • 什么是“export default”以及它与“module.exports”有何不同?
    什么是“export default”以及它与“module.exports”有何不同?
    ES6 的“默认导出”解释JavaScript 的 ES6 模块系统引入了“默认导出”,这是一种定义默认导出的独特方式。 module.在提供的示例中,文件 SafeString.js 定义了一个 SafeString 类并将其导出为默认导出using:export default SafeStri...
    编程 发布于2024-11-07
  • SafeLine 如何通过高级动态保护保护您的网站
    SafeLine 如何通过高级动态保护保护您的网站
    SafeLine 由长亭科技在过去十年中开发,是一款最先进的 Web 应用程序防火墙 (WAF),它利用先进的语义分析算法来提供针对在线威胁的顶级保护。 SafeLine 在专业网络安全圈中享有盛誉并值得信赖,已成为保护网站安全的可靠选择。 SafeLine 社区版源自企业级 Ray Shield ...
    编程 发布于2024-11-07
  • 在 React 中创建自定义 Hook 的最佳技巧
    在 React 中创建自定义 Hook 的最佳技巧
    React 的自定义 Hooks 是从组件中删除可重用功能的有效工具。它们支持代码中的 DRY(不要重复)、可维护性和整洁性。但开发有用的自定义钩子需要牢牢掌握 React 的基本思想和推荐程序。在这篇文章中,我们将讨论在 React 中开发自定义钩子的一些最佳策略,并举例说明如何有效地应用它们。 ...
    编程 发布于2024-11-07
  • 如何解决 PHPMailer 中的 HTML 渲染问题?
    如何解决 PHPMailer 中的 HTML 渲染问题?
    PHPmailer的HTML渲染问题及其解决方法在PHPmailer中,当尝试发送HTML格式的电子邮件时,用户可能会遇到一个意想不到的问题:显示实际的HTML代码在电子邮件正文中而不是预期内容中。为了有效地解决这个问题,方法调用的特定顺序至关重要。正确的顺序包括在调用 isHTML() 方法之前设...
    编程 发布于2024-11-07
  • 通过 REST API 上的 GraphQL 增强 React 应用程序
    通过 REST API 上的 GraphQL 增强 React 应用程序
    In the rapidly changing world of web development, optimizing and scaling applications is always an issue. React.js had an extraordinary success for fr...
    编程 发布于2024-11-07
  • 为什么我的登录表单无法连接到我的数据库?
    为什么我的登录表单无法连接到我的数据库?
    登录表单的数据库连接问题尽管结合使用 PHP 和 MySQL 以及 HTML 和 Dreamweaver,您仍无法建立正确的数据库连接问题。登录表单和数据库之间的连接。缺少错误消息可能会产生误导,因为登录尝试仍然不成功。连接失败的原因:数据库凭据不正确: 确保用于连接数据库的主机名、数据库名称、用...
    编程 发布于2024-11-07
  • 为什么嵌套绝对定位会导致元素引用其父级而不是祖父母?
    为什么嵌套绝对定位会导致元素引用其父级而不是祖父母?
    嵌套定位:绝对内的绝对嵌套的绝对定位元素可能会在 CSS 中表现出意想不到的行为。考虑这种情况:第一个 div (#1st) 位置:相对第二个 div (#2nd) 相对于 #1st 绝对定位A第三个div(#3rd)绝对定位在#2nd内问:为什么#3rd相对于#2nd而不是#1st绝对定位?A: ...
    编程 发布于2024-11-07
  • 如何高效地从字符串中剥离特定文本?
    如何高效地从字符串中剥离特定文本?
    高效剥离字符串:如何删除特定文本片段遇到操作字符串值的需求是编程中的常见任务。经常面临的一项特殊挑战是删除特定文本片段,同时保留特定部分。在本文中,我们将深入研究此问题的实用解决方案。考虑这样一个场景,您有一个字符串“data-123”,您的目标是消除“data-”前缀,只留下“123”值。为了实现...
    编程 发布于2024-11-07
  • 如何将通讯录与手机同步?在 Go 中实现 CardDAV!
    如何将通讯录与手机同步?在 Go 中实现 CardDAV!
    假设您帮助管理一个小型组织或俱乐部,并拥有一个存储所有会员详细信息(姓名、电话、电子邮件...)的数据库。 在您需要的任何地方都可以访问这些最新信息不是很好吗?好吧,有了 CardDAV,你就可以! CardDAV 是一个得到良好支持的联系人管理开放标准;它在 iOS 联系人应用程序和许多适用于 A...
    编程 发布于2024-11-07

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3