成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

理解 Docker 容器中 UID 和 GID 的工作原理

云計算 云原生
如果容器內部的進程正在執行的已知 uid,那么簡單地限制對主機系統的訪問,使容器中的 uid 僅具有有限訪問權限就可以了。

理解用戶名、組名、用戶ID(UID)和組ID(GID)在容器內運行的進程與主機系統之間的映射是構建安全系統的重要一環。如果沒有提供其他選項,容器中的進程將以root用戶身份執行(除非在Dockerfile中提供了不同的UID)。本文將解釋這一工作原理,如何正確授予權限,并提供示例加以說明。

逐步分析uid/gid安全性

首先,讓我們回顧一下uid和gid是如何實現的。Linux內核負責管理uid和gid空間,使用內核級系統調用來確定是否應該授予請求的特權。例如,當一個進程嘗試寫入文件時,內核會檢查創建該進程的uid和gid,以確定它是否具有足夠的特權來修改文件。這里不使用用戶名,而是使用uid。

在服務器上運行 Docker 容器時,仍然只有一個內核。容器化帶來的巨大價值之一是所有這些獨立的進程可以繼續共享一個內核。這意味著即使在運行 Docker 容器的服務器上,整個 uid 和 gid 的世界仍由一個單一內核控制。

因此,在不同的容器中不能使用相同的 uid 分配給不同的用戶。這是因為在常見的 Linux 工具中顯示的用戶名(和組名)并不是內核的一部分,而是由外部工具(如 /etc/passwd、LDAP、Kerberos 等)管理。因此,你可能會看到不同的用戶名,但是即使在不同的容器中,對于相同的 uid/gid,你也不能擁有不同的權限。這一點一開始可能會讓人感到相當困惑,所以讓我們通過幾個例子來說明一下:

簡單的Docker運行

我將首先以普通用戶(marc)的身份登錄到一個屬于docker組的服務器上。這樣我就可以在不使用sudo命令的情況下啟動docker容器。然后,從容器外部,讓我們來看看這個過程是如何呈現的。

marc@server:~$ docker run -d ubuntu:latest sleep infinity
92c57a8a4eda60678f049b906f99053cbe3bf68a7261f118e411dee173484d10
marc@server:~$ ps aux | grep sleep
root 15638 0.1 0.0 4380 808 ? Ss 19:49 0:00 sleep infinity

盡管我從未輸入過sudo,也不是root用戶,但我執行的sleep命令以root用戶身份啟動并具有root權限。我如何知道它具有root權限?容器內的root是否等同于容器外的root?是的,因為正如我提到的,有一個單一的內核和一個共享的uid和gid池。由于容器外顯示的用戶名是“root”,我可以確定容器內的進程是以具有uid = 0的用戶啟動的。

帶有定義用戶的Dockerfile

當我在 Dockerfile 中創建一個不同的用戶并以該用戶身份啟動命令時會發生什么?為了簡化這個例子,我這里沒有指定 gid,但相同的概念也適用于組 id。

首先,我正在以用戶名為“marc”的用戶身份運行這些命令,該用戶的用戶ID為1001。

marc@server:~$ echo $UID
1001

Dockerfile文件:

FROM ubuntu:latest
RUN useradd -r -u 1001 -g appuser appuser
USER appuser
ENTRYPOINT [“sleep”, “infinity”]

構建:

marc@server:~$ docker build -t test .
Sending build context to Docker daemon 14.34 kB
Step 1/4 : FROM ubuntu:latest
 — -> f49eec89601e
Step 2/4 : RUN useradd -r -u 1001 appuser
 — -> Running in 8c4c0a442ace
 — -> 6a81547f335e
Removing intermediate container 8c4c0a442ace
Step 3/4 : USER appuser
 — -> Running in acd9e30b4aba
 — -> fc1b765e227f
Removing intermediate container acd9e30b4aba
Step 4/4 : ENTRYPOINT sleep infinity
 — -> Running in a5710a32a8ed
 — -> fd1e2ab0fb75
Removing intermediate container a5710a32a8ed
Successfully built fd1e2ab0fb75
marc@server:~$ docker run -d test
8ad0cd43592e6c4314775392fb3149015adc25deb22e5e5ea07203ff53038073
marc@server:~$ ps aux | grep sleep
marc 16507 0.3 0.0 4380 668 ? Ss 20:02 0:00 sleep infinity
marc@server:~$ docker exec -it 8ad0 /bin/bash
appuser@8ad0cd43592e:/$ ps aux | grep sleep
appuser 1 0.0 0.0 4380 668 ? Ss 20:02 0:00 sleep infinity

這里到底發生了什么,這意味著什么?我構建了一個 Docker 鏡像,其中有一個名為“appuser”的用戶,該用戶的 uid 為 1001。在我的測試服務器上,我使用的帳戶名為“marc”,uid 也是 1001。當我啟動容器時,sleep 命令以 appuser 的身份執行,因為 Dockerfile 包含了“USER appuser”這一行。但實際上這并不是以 appuser 的身份運行,而是以 Docker 鏡像中被識別為 appuser 的用戶的 uid 運行。

當我檢查容器外運行的進程時,我發現它映射到用戶“marc”,但在容器內部,它映射到用戶“appuser”。這兩個用戶名只是顯示它們的執行上下文所知道的映射到1001的用戶名。

這并不是非常重要。但重要的是要知道,在容器內部,用戶“appuser”獲得了來自容器外部用戶“marc”的權限和特權。在Linux主機上授予用戶marc或uid 1001的權限也將授予容器內的appuser這些權限。

如何控制容器的訪問權限

另一種選擇是在運行 Docker 容器時指定用戶名或用戶ID,以及組名或組ID。

再次使用上面的初始示例。

marc@server:~$ docker run -d --user 1001 ubuntu:latest sleep infinity
84f436065c90ac5f59a2256e8a27237cf8d7849d18e39e5370c36f9554254e2b
marc@server$ ps aux | grep sleep
marc     17058 0.1 0.0 4380 664 ? Ss 21:23 0:00 sleep infinity

我在這里做了什么?我創建了容器以1001用戶身份啟動。因此,當我執行諸如ps或top(或大多數監控工具)之類的命令時,進程映射到“marc”用戶。

有趣的是,當我進入該容器時,你會發現1001用戶在/etc/passwd文件中沒有條目,并在容器的bash提示符中顯示為“I have no name!”。

marc@server:~$ docker exec -it 84f43 /bin/bash
I have no name!@84f436065c90:/$

重要的是要注意,在創建容器時指定用戶標志也會覆蓋 Dockerfile 中的值。還記得第二個例子嗎?那時我使用了一個 Dockerfile,其中的 uid 映射到本地主機上的不同用戶名。當我們在命令行上使用用戶標志來啟動一個執行“sleep infinity”進程的容器時,會發生什么呢?

marc@server:$ docker run -d test
489a236261a0620e287e434ed1b15503c844648544694e538264e69d534d0d65
marc@server:~$ ps aux | grep sleep
marc     17689 0.2 0.0 4380 680 ? Ss 21:28 0:00 sleep infinity
marc@server:~$ docker run --user 0 -d test
ac27849fcbce066bad37190b5bf6a46cf526f56d889af61e7a02c3726438fa7a
marc@server:~$ ps aux | grep sleep
marc     17689 0.0 0.0 4380 680 ? Ss 21:28 0:00 sleep infinity
root     17783 0.3 0.0 4380 668 ? Ss 21:28 0:00 sleep infinity

在上面的最后一個示例中,您可以看到我最終得到了兩個運行睡眠進程的容器,一個是“marc”,另一個是“root”。這是因為第二個命令通過在命令行上傳遞--user標志來更改了用戶ID。

總結

現在我們已經探討了這一點,可以理解以有限權限運行容器的方式都利用了主機的用戶系統:

  • 如果容器內部的進程正在執行的已知 uid,那么簡單地限制對主機系統的訪問,使容器中的 uid 僅具有有限訪問權限就可以了。
  • 更好的解決方案是使用--user以已知 uid 啟動容器(也可以使用用戶名,但請記住這只是提供主機用戶名系統中的 uid 的一種更友好的方式),然后限制主機上您決定容器將以其運行的 uid 的訪問權限。
  • 由于容器到主機的 uid 和用戶名(以及 gid 和組名)的映射,指定容器化進程運行的用戶可以使該進程在容器內部和外部看起來像是由不同的用戶擁有。
責任編輯:武曉燕 來源: 云原生運維圈
相關推薦

2019-08-20 14:01:22

HTTPSSSL協議

2022-09-06 11:13:16

接口PipelineHandler

2024-06-27 08:26:10

LooperAndroid內存

2024-11-01 08:57:07

2022-07-29 10:01:50

Docker退出碼

2015-01-06 15:25:12

DockerDocker Volu數據容器

2009-07-06 16:16:33

Servlet容器工作

2023-09-19 22:47:39

Java內存

2021-07-16 07:57:34

ReduxDOM組件

2025-04-01 08:50:48

2019-07-16 14:44:52

DockerMySQL操作系統

2009-11-30 17:30:47

PHP ereg_re

2019-07-24 08:49:36

Docker容器鏡像

2011-07-01 11:16:14

Struts

2018-07-24 08:56:45

容器存儲閃存

2015-08-26 15:11:41

Docker容器備份Docker容器遷移

2022-01-05 14:30:44

容器Linux網絡

2022-05-11 07:38:45

SpringWebFlux

2024-08-14 18:18:47

2023-10-25 12:51:28

Go調度器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久一二区 | 精品伊人 | 欧美成人免费在线视频 | 欧美精品在线观看 | 久久国产精品一区二区三区 | 精品综合久久 | 国产精品高清一区二区三区 | 91中文字幕在线观看 | 中文字幕欧美一区 | 国产不卡一 | 玖玖精品 | 中文av网站| 日韩在线精品 | 麻豆精品一区二区三区在线观看 | 久久精品二区亚洲w码 | 九色视频网站 | 中文字幕一级 | 亚洲高清成人在线 | 成人亚洲视频 | 在线第一页 | av中文字幕网 | 欧美日韩亚洲视频 | 日韩综合 | 欧美中文一区 | 亚洲网视频| 亚洲国产精品视频一区 | 亚洲综合日韩精品欧美综合区 | 亚洲小视频在线播放 | 亚洲一区成人 | 成人亚洲精品久久久久软件 | 欧美国产亚洲一区二区 | 久久久妇女国产精品影视 | www.久久久久久久久久久 | 国产精品久久国产精品久久 | 99久久精品免费看国产四区 | 亚洲欧美日韩系列 | 色视频在线播放 | 国产精品视频一二三区 | 久久99精品久久久久久秒播九色 | 精精国产xxxx视频在线播放7 | 激情av网站|