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

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

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

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]删除
最新教程 更多>
  • 如何限制动态大小的父元素中元素的滚动范围?
    如何限制动态大小的父元素中元素的滚动范围?
    在交互式接口中实现垂直滚动元素的CSS高度限制问题:考虑一个布局,其中我们具有与用户垂直滚动一起移动的可滚动地图div,同时与固定的固定sidebar保持一致。但是,地图的滚动无限期扩展,超过了视口的高度,阻止用户访问页面页脚。$("#map").css({ marginT...
    编程 发布于2025-07-14
  • 为什么不使用CSS`content'属性显示图像?
    为什么不使用CSS`content'属性显示图像?
    在Firefox extemers属性为某些图像很大,&& && && &&华倍华倍[华氏华倍华氏度]很少见,却是某些浏览属性很少,尤其是特定于Firefox的某些浏览器未能在使用内容属性引用时未能显示图像的情况。这可以在提供的CSS类中看到:。googlepic { 内容:url(&#...
    编程 发布于2025-07-14
  • Python中嵌套函数与闭包的区别是什么
    Python中嵌套函数与闭包的区别是什么
    嵌套函数与python 在python中的嵌套函数不被考虑闭合,因为它们不符合以下要求:不访问局部范围scliables to incling scliables在封装范围外执行范围的局部范围。 make_printer(msg): DEF打印机(): 打印(味精) ...
    编程 发布于2025-07-14
  • 反射动态实现Go接口用于RPC方法探索
    反射动态实现Go接口用于RPC方法探索
    在GO 使用反射来实现定义RPC式方法的界面。例如,考虑一个接口,例如:键入myService接口{ 登录(用户名,密码字符串)(sessionId int,错误错误) helloworld(sessionid int)(hi String,错误错误) } 替代方案而不是依靠反射...
    编程 发布于2025-07-14
  • 大批
    大批
    [2 数组是对象,因此它们在JS中也具有方法。 切片(开始):在新数组中提取部分数组,而无需突变原始数组。 令ARR = ['a','b','c','d','e']; // USECASE:提取直到索引作...
    编程 发布于2025-07-14
  • 如何在鼠标单击时编程选择DIV中的所有文本?
    如何在鼠标单击时编程选择DIV中的所有文本?
    在鼠标上选择div文本单击带有文本内容,用户如何使用单个鼠标单击单击div中的整个文本?这允许用户轻松拖放所选的文本或直接复制它。 在单个鼠标上单击的div元素中选择文本,您可以使用以下Javascript函数: function selecttext(canduterid){ if(do...
    编程 发布于2025-07-14
  • 找到最大计数时,如何解决mySQL中的“组函数\”错误的“无效使用”?
    找到最大计数时,如何解决mySQL中的“组函数\”错误的“无效使用”?
    如何在mySQL中使用mySql 检索最大计数,您可能会遇到一个问题,您可能会在尝试使用以下命令:理解错误正确找到由名称列分组的值的最大计数,请使用以下修改后的查询: 计数(*)为c 来自EMP1 按名称组 c desc订购 限制1 查询说明 select语句提取名称列和每个名称...
    编程 发布于2025-07-14
  • 左连接为何在右表WHERE子句过滤时像内连接?
    左连接为何在右表WHERE子句过滤时像内连接?
    左JOIN CONUNDRUM:WITCHING小时在数据库Wizard的领域中变成内在的加入很有趣,当将c.foobar条件放置在上面的Where子句中时,据说左联接似乎会转换为内部连接。仅当满足A.Foo和C.Foobar标准时,才会返回结果。为什么要变形?关键在于其中的子句。当左联接的右侧值...
    编程 发布于2025-07-14
  • 您可以使用CSS在Chrome和Firefox中染色控制台输出吗?
    您可以使用CSS在Chrome和Firefox中染色控制台输出吗?
    在javascript console 中显示颜色是可以使用chrome的控制台显示彩色文本,例如红色的redors,for for for for错误消息?回答是的,可以使用CSS将颜色添加到Chrome和Firefox中的控制台显示的消息(版本31或更高版本)中。要实现这一目标,请使用以下模...
    编程 发布于2025-07-14
  • JavaScript计算两个日期之间天数的方法
    JavaScript计算两个日期之间天数的方法
    How to Calculate the Difference Between Dates in JavascriptAs you attempt to determine the difference between two dates in Javascript, consider this s...
    编程 发布于2025-07-14
  • 在Java中使用for-to-loop和迭代器进行收集遍历之间是否存在性能差异?
    在Java中使用for-to-loop和迭代器进行收集遍历之间是否存在性能差异?
    For Each Loop vs. Iterator: Efficiency in Collection TraversalIntroductionWhen traversing a collection in Java, the choice arises between using a for-...
    编程 发布于2025-07-14
  • Spark DataFrame添加常量列的妙招
    Spark DataFrame添加常量列的妙招
    在Spark Dataframe ,将常数列添加到Spark DataFrame,该列具有适用于所有行的任意值的Spark DataFrame,可以通过多种方式实现。使用文字值(SPARK 1.3)在尝试提供直接值时,用于此问题时,旨在为此目的的column方法可能会导致错误。 df.withCo...
    编程 发布于2025-07-14
  • 如何使用Java.net.urlConnection和Multipart/form-data编码使用其他参数上传文件?
    如何使用Java.net.urlConnection和Multipart/form-data编码使用其他参数上传文件?
    使用http request 上传文件上传到http server,同时也提交其他参数,java.net.net.urlconnection and Multipart/form-data Encoding是普遍的。 Here's a breakdown of the process:Mu...
    编程 发布于2025-07-14
  • 如何在JavaScript对象中动态设置键?
    如何在JavaScript对象中动态设置键?
    在尝试为JavaScript对象创建动态键时,如何使用此Syntax jsObj['key' i] = 'example' 1;不工作。正确的方法采用方括号: jsobj ['key''i] ='example'1; 在JavaScript中,数组是一...
    编程 发布于2025-07-14
  • `console.log`显示修改后对象值异常的原因
    `console.log`显示修改后对象值异常的原因
    foo = [{id:1},{id:2},{id:3},{id:4},{id:id:5},],]; console.log('foo1',foo,foo.length); foo.splice(2,1); console.log('foo2', foo, foo....
    编程 发布于2025-07-14

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

Copyright© 2022 湘ICP备2022001581号-3