我將首先以 docker 組中的普通用戶(marc)身份登陸服務器。這容許我在不使用 sudo 命令的狀況下啓動 docker 容器。而後,從容器外部,讓咱們看看這個過程是如何出現的。linux
marc@server:~$ docker run -d ubuntu:latest sleep infinity92c57a8a4eda60678f049b906f99053cbe3bf68a7261f118e411dee173484d10marc@server:~$ ps aux | grep sleeproot 15638 0.1 0.0 4380 808 ? Ss 19:49 0:00 sleep infinity複製代碼
有趣。即便我從未輸入 sudo 而且我不是 root 用戶,我執行的 sleep 命令也以root 用戶身份啓動並具備 root 權限。我怎麼知道它有 root 權限?容器內的 root = =容器外的 root 嗎?是的,由於正如我所提到的,有一個內核和一個共享的 uids 和 gids 池。由於用戶名在容器外部顯示爲「root」,因此我能夠確定地知道容器內的進程是由具備uid = 0的用戶啓動的。docker
當我在 Dockerfile 中建立不一樣的用戶並以該用戶身份啓動命令時會發生什麼?爲了簡化這個例子,我沒有在這裏指定一個gid,但一樣的概念適用於組ID.ubuntu
首先,我將這些命令做爲用戶「marc」運行,其 uid 爲1001。安全
marc@server:~$ echo $UID1001複製代碼
和 Dockerfile:bash
FROM ubuntu:latestRUN useradd -r -u 1001 -g appuser appuserUSER appuserENTRYPOINT [「sleep」, 「infinity」]複製代碼
讓咱們構建並運行它:服務器
marc@server:~$ docker build -t test .Sending build context to Docker daemon 14.34 kBStep 1/4 : FROM ubuntu:latest — -> f49eec89601eStep 2/4 : RUN useradd -r -u 1001 appuser — -> Running in 8c4c0a442ace — -> 6a81547f335eRemoving intermediate container 8c4c0a442aceStep 3/4 : USER appuser — -> Running in acd9e30b4aba — -> fc1b765e227fRemoving intermediate container acd9e30b4abaStep 4/4 : ENTRYPOINT sleep infinity — -> Running in a5710a32a8ed — -> fd1e2ab0fb75Removing intermediate container a5710a32a8edSuccessfully built fd1e2ab0fb75marc@server:~$ docker run -d test8ad0cd43592e6c4314775392fb3149015adc25deb22e5e5ea07203ff53038073marc@server:~$ ps aux | grep sleepmarc 16507 0.3 0.0 4380 668 ? Ss 20:02 0:00 sleep infinitymarc@server:~$ docker exec -it 8ad0 /bin/bashappuser@8ad0cd43592e:/$ ps aux | grep sleepappuser 1 0.0 0.0 4380 668 ? Ss 20:02 0:00 sleep infinity複製代碼
marc@server:~$ docker run -d --user 1001 ubuntu:latest sleep infinity84f436065c90ac5f59a2256e8a27237cf8d7849d18e39e5370c36f9554254e2bmarc@server$ ps aux | grep sleepmarc 17058 0.1 0.0 4380 664 ? Ss 21:23 0:00 sleep infinity複製代碼
marc@server:~$ docker exec -it 84f43 /bin/bashI have no name!@84f436065c90:/$複製代碼
須要注意的是,在建立容器時指定用戶標誌也會覆蓋 Dockerfile 中的該值。還記得第二個例子,我使用的 Dockerfile 有一個映射到本地主機上不一樣用戶名的uid嗎?當咱們在命令行上使用用戶標誌運行它以啓動執行「睡眠無限」過程的容器時會發生什麼?app
marc@server:$ docker run -d test489a236261a0620e287e434ed1b15503c844648544694e538264e69d534d0d65marc@server:~$ ps aux | grep sleepmarc 17689 0.2 0.0 4380 680 ? Ss 21:28 0:00 sleep infinitymarc@server:~$ docker run --user 0 -d testac27849fcbce066bad37190b5bf6a46cf526f56d889af61e7a02c3726438fa7amarc@server:~$ ps aux | grep sleepmarc 17689 0.0 0.0 4380 680 ? Ss 21:28 0:00 sleep infinityroot 17783 0.3 0.0 4380 668 ? Ss 21:28 0:00 sleep infinity複製代碼
在上面的最後一個例子中,你能夠看到我最終有2個容器運行睡眠過程,一個用做「marc」,另外一個用做「root」。這是由於第二個命令經過--user 在命令行上傳遞標誌來更改uid.
工具
一、若是已知的 uid 表示容器內的進程正在執行,則可能就像限制對主機系統的訪問同樣簡單,以便容器中的 uid 有有限的訪問權限。測試
二、更好的解決方案是使用已知的 uid 啓動容器--user(您也可使用用戶名,但請記住,它只是從主機的用戶名系統提供uid的更友好的方式),而後限制對主機上的 uid 的訪問你決定容器將運行爲。ui
三、因爲 uid 和用戶名(以及gid和組名稱)如何從容器映射到主機,所以指定容器化進程運行的用戶可使進程看起來由內部和容器外部的不一樣用戶擁有。
- end -
做者:Marc Campbell
本文轉載於外網,轉載請標明出處