」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 使用 docker_userid_fixer 修復 docker 容器中的使用者 ID 的優雅方法

使用 docker_userid_fixer 修復 docker 容器中的使用者 ID 的優雅方法

發佈於2024-11-01
瀏覽:621

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]刪除
最新教學 更多>
  • 為什麼Microsoft Visual C ++無法正確實現兩台模板的實例?
    為什麼Microsoft Visual C ++無法正確實現兩台模板的實例?
    The Mystery of "Broken" Two-Phase Template Instantiation in Microsoft Visual C Problem Statement:Users commonly express concerns that Micro...
    程式設計 發佈於2025-07-02
  • 在程序退出之前,我需要在C ++中明確刪除堆的堆分配嗎?
    在程序退出之前,我需要在C ++中明確刪除堆的堆分配嗎?
    在C中的顯式刪除 在C中的動態內存分配時,開發人員通常會想知道是否有必要在heap-procal extrable exit exit上進行手動調用“ delete”操作員,但開發人員通常會想知道是否需要手動調用“ delete”操作員。本文深入研究了這個主題。 在C主函數中,使用了動態分配變量(...
    程式設計 發佈於2025-07-02
  • \“(1)vs.(;;):編譯器優化是否消除了性能差異?\”
    \“(1)vs.(;;):編譯器優化是否消除了性能差異?\”
    答案: 在大多數現代編譯器中,while(1)和(1)和(;;)之間沒有性能差異。編譯器: perl: 1 輸入 - > 2 2 NextState(Main 2 -E:1)V-> 3 9 Leaveloop VK/2-> A 3 toterloop(next-> 8 last-> 9 ...
    程式設計 發佈於2025-07-02
  • Java中如何使用觀察者模式實現自定義事件?
    Java中如何使用觀察者模式實現自定義事件?
    在Java 中創建自定義事件的自定義事件在許多編程場景中都是無關緊要的,使組件能夠基於特定的觸發器相互通信。本文旨在解決以下內容:問題語句我們如何在Java中實現自定義事件以促進基於特定事件的對象之間的交互,定義了管理訂閱者的類界面。 以下代碼片段演示瞭如何使用觀察者模式創建自定義事件: args...
    程式設計 發佈於2025-07-02
  • PHP陣列鍵值異常:了解07和08的好奇情況
    PHP陣列鍵值異常:了解07和08的好奇情況
    PHP數組鍵值問題,使用07&08 在給定數月的數組中,鍵值07和08呈現令人困惑的行為時,就會出現一個不尋常的問題。運行print_r($月)返回意外結果:鍵“ 07”丟失,而鍵“ 08”分配給了9月的值。 此問題源於PHP對領先零的解釋。當一個數字帶有0(例如07或08)的前綴時,PHP將...
    程式設計 發佈於2025-07-02
  • MySQL中如何高效地根據兩個條件INSERT或UPDATE行?
    MySQL中如何高效地根據兩個條件INSERT或UPDATE行?
    在兩個條件下插入或更新或更新 solution:的答案在於mysql的插入中...在重複鍵更新語法上。如果不存在匹配行或更新現有行,則此功能強大的功能可以通過插入新行來進行有效的數據操作。如果違反了唯一的密鑰約束。 實現所需的行為,該表必須具有唯一的鍵定義(在這種情況下為'名稱'...
    程式設計 發佈於2025-07-02
  • 版本5.6.5之前,使用current_timestamp與時間戳列的current_timestamp與時間戳列有什麼限制?
    版本5.6.5之前,使用current_timestamp與時間戳列的current_timestamp與時間戳列有什麼限制?
    在時間戳列上使用current_timestamp或MySQL版本中的current_timestamp或在5.6.5 此限制源於遺留實現的關注,這些限制需要對當前的_timestamp功能進行特定的實現。 創建表`foo`( `Productid` int(10)unsigned not ...
    程式設計 發佈於2025-07-02
  • 如何使用組在MySQL中旋轉數據?
    如何使用組在MySQL中旋轉數據?
    在關係數據庫中使用mySQL組使用mySQL組進行查詢結果,在關係數據庫中使用MySQL組,轉移數據的數據是指重新排列的行和列的重排以增強數據可視化。在這裡,我們面對一個共同的挑戰:使用組的組將數據從基於行的基於列的轉換為基於列。 Let's consider the following ...
    程式設計 發佈於2025-07-02
  • 如何克服PHP的功能重新定義限制?
    如何克服PHP的功能重新定義限制?
    克服PHP的函數重新定義限制在PHP中,多次定義一個相同名稱的函數是一個no-no。嘗試這樣做,如提供的代碼段所示,將導致可怕的“不能重新列出”錯誤。 但是,PHP工具腰帶中有一個隱藏的寶石:runkit擴展。它使您能夠靈活地重新定義函數。 runkit_function_renction_...
    程式設計 發佈於2025-07-02
  • 為什麼PYTZ最初顯示出意外的時區偏移?
    為什麼PYTZ最初顯示出意外的時區偏移?
    與pytz 最初從pytz獲得特定的偏移。例如,亞洲/hong_kong最初顯示一個七個小時37分鐘的偏移: 差異源利用本地化將時區分配給日期,使用了適當的時區名稱和偏移量。但是,直接使用DateTime構造器分配時區不允許進行正確的調整。 example pytz.timezone(&#...
    程式設計 發佈於2025-07-02
  • 在Ubuntu/linux上安裝mysql-python時,如何修復\“ mysql_config \”錯誤?
    在Ubuntu/linux上安裝mysql-python時,如何修復\“ mysql_config \”錯誤?
    mysql-python安裝錯誤:“ mysql_config找不到”“ 由於缺少MySQL開發庫而出現此錯誤。解決此問題,建議在Ubuntu上使用該分發的存儲庫。使用以下命令安裝Python-MysqldB: sudo apt-get安裝python-mysqldb sudo pip in...
    程式設計 發佈於2025-07-02
  • 如何限制動態大小的父元素中元素的滾動範圍?
    如何限制動態大小的父元素中元素的滾動範圍?
    在交互式接口中實現垂直滾動元素的CSS高度限制問題:考慮一個佈局,其中我們具有與用戶垂直滾動一起移動的可滾動地圖div,同時與固定的固定sidebar保持一致。但是,地圖的滾動無限期擴展,超過了視口的高度,阻止用戶訪問頁面頁腳。 $("#map").css({ margin...
    程式設計 發佈於2025-07-02
  • 查找當前執行JavaScript的腳本元素方法
    查找當前執行JavaScript的腳本元素方法
    如何引用當前執行腳本的腳本元素在某些方案中理解問題在某些方案中,開發人員可能需要將其他腳本動態加載其他腳本。但是,如果Head Element尚未完全渲染,則使用document.getElementsbytagname('head')[0] .appendChild(v)的常規方...
    程式設計 發佈於2025-07-02
  • Python環境變量的訪問與管理方法
    Python環境變量的訪問與管理方法
    Accessing Environment Variables in PythonTo access environment variables in Python, utilize the os.environ object, which represents a mapping of envir...
    程式設計 發佈於2025-07-02

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3