Container 內的 user 預設為 root (UID=0),下圖使用預設user = root 啟動container
無論Containerfile/Dockerfile中指定什麼USER,啟動container時可指定 user 或UID來啟動,此user一定會是 root group 成員,GID=0。下圖使用UID=1000 啟動container
請注意 /etc/passwd 不存在UID=1000 這個user,
whoami
指令回傳錯誤訊息。
Red Hat OpenShift Container Platform 以下簡稱OCP
Security Context Constraints 以下簡稱SCC
OCP SCC機制限制 container user UID 範圍,OCP啟動container時使用隨機UID啟動該container,預設UID範圍是一組十碼的UID,例如1000620000。這樣的機制忽略Containerfile/Dockerfile中指定的USER,由OCP隨機指定UID。
OCP管理員可限制每個namespace允許的 UID 範圍。
References
設計container時,不使用root啟動container。
為了使任一且無法事先預知的 non-root user 皆有權限執行該container服務,設計container時,也就是製作container image的時候,需將container服務啟動時所需的路徑權限 (file permissions) 設定屬於 root group,且依據需求給予 root group 適當的讀取、寫入、或執行權限,確保任何一個隨機 non-root user 皆有權限啟動該container。
如果設計container時,沒有考慮任一user啟動,Containerfile/Dockerfile 已經寫好了USER, UID=1000,此user所需變數寫於該user profiles中 (.bash_profile, .bashrc等),屬於root group的任一user沒有這些變數,無法啟動服務。也就是說,這個container image的設計只能使用指定user,不能使用任一user啟動。
OCP管理員允許namespace使用 UID=1000,詳細作法可參考以下文章
OCP管理員無法允許指定UID時,須重新設計container image 適應任一隨機user啟動。
在最小變動的期望下,於 container中的啟動腳本加入以下代碼,判斷 whoami
是否成功,不成功代表當前UID是OCP隨機指派的,此UID不在我設計的container的 /etc/passwd;當此狀況發生,將當前UID寫入 /etc/passwd,並且使用exec
命令重啟container,此重啟container 的process 取代更改/etc/passwd之前的process。
!#/bin/bash if ! whoami &> /dev/null; then if [ -w /etc/passwd ]; then echo "Setting etc passwd entry for $(id -u)" echo "oci-user:x:$(id -u):0:Arbitrary user:/home/controlm:/bin/bash" >> /etc/passwd if [ $? -eq 0 ]; then exec ./$0 $@ else echo "Failed to update etc users" fi fi fi
於我的 container中的啟動腳本加入以上代碼的執行結果,下圖 container user=oci-user,UID=1000620000,/etc/passwd有此user。
此隨機的user雖然與我於Containerfile/Dockerfile中指定的USER不同,但兩者$HOME相同,user profiles相同,可讀取相同變數,此隨機的user可成功啟動container 服務。
筆者曾經試圖於Containerfile/Dockerfile 建立 UID=1000620000 的一個 user,企圖暫時解決困境,發現此舉不可為。此篇文章述說的困境,是許多container啟動時所需的組態檔、執行檔放在我於Containerfile/Dockerfile創建的user 的家目錄,當此UID為十碼,$HOME 會相當大,打包完成的image大小超過10G,不可為。