首頁 / 手冊 / Docker 引擎 / 安全性 / 無根模式 無根模式允許以非 root 使用者身分執行 Docker Daemon 和容器,以減輕 Daemon 和容器執行階段中潛在的弱點。
只要滿足先決條件 ,無根模式即使在安裝 Docker Daemon 期間也不需要 root 權限。
無根模式在使用者命名空間內執行 Docker Daemon 和容器。這與userns-remap
模式 非常相似,不同之處在於使用 userns-remap
模式時,Daemon 本身是以 root 權限執行的,而在無根模式下,Daemon 和容器都以非 root 權限執行。
無根模式不使用具有 SETUID
位元或檔案功能的二進位檔,但 newuidmap
和 newgidmap
例外,它們允許在使用者命名空間中使用多個 UID/GID。
您必須在主機上安裝 newuidmap
和 newgidmap
。這些命令由大多數發行版本上的 uidmap
套件提供。
/etc/subuid
和 /etc/subgid
應至少包含 65,536 個使用者的從屬 UID/GID。在以下範例中,使用者 testuser
具有 65,536 個從屬 UID/GID (231072-296607)。
提示
建議您使用 Ubuntu 核心。
Ubuntu
Debian GNU/Linux
Arch Linux
openSUSE 和 SLES
CentOS、RHEL 和 Fedora
如果未安裝 dbus-user-session
套件,請安裝它。執行 sudo apt-get install -y dbus-user-session
並重新登入。
對於 Debian 10,請將 kernel.unprivileged_userns_clone=1
新增至 /etc/sysctl.conf
(或 /etc/sysctl.d
) 並執行 sudo sysctl --system
。Debian 11 不需要此步驟。
對於 Debian 11,建議安裝 fuse-overlayfs
。執行 sudo apt-get install -y fuse-overlayfs
。Debian 12 不需要此步驟。
無根 Docker 需要大於 v0.4.0
版本的 slirp4netns
(未安裝 vpnkit
時)。使用以下命令檢查您是否擁有此版本
如果您沒有安裝 `slirp4netns`,請使用 `sudo apt-get install -y slirp4netns` 指令安裝,或下載最新的 版本 。
對於 openSUSE 15 和 SLES 15,建議安裝 `fuse-overlayfs`。執行 `sudo zypper install -y fuse-overlayfs` 指令。openSUSE Tumbleweed 不需要此步驟。
需要執行 `sudo modprobe ip_tables iptable_mangle iptable_nat iptable_filter` 指令。根據配置,其他發行版可能也需要執行此指令。
已知可在 openSUSE 15 和 SLES 15 上運作。
僅支援以下儲存驅動程式:`overlay2`(僅在使用核心 5.11 或更高版本,或 Ubuntu 風格的核心時) `fuse-overlayfs`(僅在使用核心 4.18 或更高版本,且已安裝 `fuse-overlayfs` 時) `btrfs`(僅在使用核心 4.18 或更高版本,或 `~/.local/share/docker` 掛載了 `user_subvol_rm_allowed` 掛載選項時) vfs
僅在使用 cgroup v2 和 systemd 運行時才支援 Cgroup。請參閱限制資源 。 不支援以下功能: 要使用 `ping` 指令,請參閱路由 ping 封包 。 要公開特權 TCP/UDP 埠(< 1024),請參閱公開特權埠 。 `docker inspect` 顯示的 `IPAddress` 位於 RootlessKit 的網路命名空間內。這表示若不使用 `nsenter` 進入網路命名空間,則無法從主機訪問該 IP 位址。 主機網路(`docker run --net=host`)也位於 RootlessKit 的命名空間內。 不支援將 NFS 掛載為 docker 的「data-root」。此限制並非 rootless 模式特有的。 **注意**
如果系統級 Docker 守护程序已在運行,請考慮將其停用。
如果您選擇不安裝關閉 `docker` 服務和通訊端,則需要在下一節中使用 `--force` 參數。目前沒有已知問題,但在您關閉並停用之前,您仍在運行 rootful Docker。
使用套件(RPM/DEB)
不使用套件
如果您使用RPM/DEB 套件 安裝了 Docker 20.10 或更高版本,則 `/usr/bin` 中應該會有 `dockerd-rootless-setuptool.sh`。
以非 root 使用者身分執行 `dockerd-rootless-setuptool.sh install` 來設定守护程序。
如果沒有 `dockerd-rootless-setuptool.sh`,您可能需要手動安裝 `docker-ce-rootless-extras` 套件,例如:
如果遇到錯誤,請參閱疑難排解 。
要移除 Docker 守护程序的 systemd 服務,請執行 `dockerd-rootless-setuptool.sh uninstall` 指令。
如果您已將環境變數 PATH 和 DOCKER_HOST 加入到 `~/.bashrc` 中,請取消設定它們。
要移除資料目錄,請執行 `rootlesskit rm -rf ~/.local/share/docker` 指令。
要移除二進制檔案,如果您使用套件管理程式安裝了 Docker,請移除 `docker-ce-rootless-extras` 套件。如果您使用 https://get.docker.com/rootless (不使用套件安裝 )安裝了 Docker,請移除 `~/bin` 下的二進制檔案。
使用 systemd(強烈建議)
不使用 systemd
systemd 單元檔案安裝為 `~/.config/systemd/user/docker.service`。
使用 `systemctl --user` 來管理守护程序的生命週期。
要在系統啟動時啟動守护程序,請啟用 systemd 服務和 lingering。
即使使用 `User=` 指令,也不支援將 Rootless Docker 作為系統級服務(`/etc/systemd/system/docker.service`)啟動。
要在沒有 systemd 的情況下直接運行守护程序,您需要運行 `dockerd-rootless.sh` 而不是 `dockerd`。
必須設定以下環境變數:
`$HOME`:家目錄 `$XDG_RUNTIME_DIR`:一個只有預期使用者可以訪問的臨時目錄,例如 `~/.docker/run`。該目錄應在每次主機關閉時移除。該目錄可以在 tmpfs 上,但不應位於 `/tmp` 下。將此目錄放在 `/tmp` 下可能容易受到 TOCTOU 攻擊。 關於目錄路徑的備註
通訊端路徑預設設定為 `$XDG_RUNTIME_DIR/docker.sock`。`$XDG_RUNTIME_DIR` 通常設定為 `/run/user/$UID`。 資料目錄預設設定為 `~/.local/share/docker`。資料目錄不應位於 NFS 上。 守护程序配置目錄預設設定為 `~/.config/docker`。此目錄與客戶端使用的 `~/.docker` 不同。 您需要明確指定通訊端路徑或 CLI 上下文。
使用 `$DOCKER_HOST` 指定通訊端路徑
使用 `docker context` 指定 CLI 上下文
要在「rootful」Docker 內運行 Rootless Docker,請使用 `docker:<version>-dind-rootless` 鏡像而不是 `docker:<version>-dind`。
`docker:<version>-dind-rootless` 鏡像以非 root 使用者(UID 1000)身分運行。但是,需要 `--privileged` 來停用 seccomp、AppArmor 和掛載遮罩。
要透過 TCP 公開 Docker API 通訊端,您需要使用 `DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="-p 0.0.0.0:2376:2376/tcp"` 啟動 `dockerd-rootless.sh`。
要透過 SSH 公開 Docker API 通訊端,您需要確保在遠端主機上設定了 `$DOCKER_HOST`。
在某些發行版上,`ping` 預設不起作用。
將 `net.ipv4.ping_group_range = 0 2147483647` 加入到 `/etc/sysctl.conf`(或 `/etc/sysctl.d`)檔案中,並執行 `sudo sysctl --system` 指令以允許使用 `ping`。
要公開特權埠(< 1024),請在 `rootlesskit` 二進制檔案上設定 `CAP_NET_BIND_SERVICE` 並重新啟動守护程序。
或者將 `net.ipv4.ip_unprivileged_port_start=0` 加入到 `/etc/sysctl.conf`(或 `/etc/sysctl.d`)檔案中,並執行 `sudo sysctl --system` 指令。
僅在使用 cgroup v2 和 systemd 運行時,才支援使用與 cgroup 相關的 `docker run` 旗標(例如 `--cpus`、`--memory`、`--pids-limit`)來限制資源。請參閱更改 cgroup 版本 以啟用 cgroup v2。
如果 `docker info` 將 `Cgroup Driver` 顯示為 `none`,則表示不滿足條件。當不滿足這些條件時,rootless 模式會忽略與 cgroup 相關的 `docker run` 旗標。請參閱在沒有 cgroup 的情況下限制資源 以了解解決方法。
如果 `docker info` 將 `Cgroup Driver` 顯示為 `systemd`,則表示滿足條件。但是,通常預設情況下只有 `memory` 和 `pids` 控制器會委派給非 root 使用者。
要允許委派所有控制器,您需要如下更改 systemd 配置:
**注意**
委派 `cpuset` 需要 systemd 244 或更高版本。
即使 cgroup 不可用,您仍然可以使用傳統的 `ulimit` 和 `cpulimit` ,但它們以程序粒度而不是容器粒度工作,並且可以被容器程序任意停用。
例如:
要將 CPU 使用率限制為 0.5 個核心(類似於 `docker run --cpus 0.5`):`docker run <IMAGE> cpulimit --limit=50 --include-children <COMMAND>`
要將最大 VSZ 限制為 64MiB(類似於 `docker run --memory 64m`):`docker run <IMAGE> sh -c "ulimit -v 65536; <COMMAND>"`
要將每個命名空間 UID 2000 的最大程序數限制為 100(類似於 `docker run --pids-limit=100`):`docker run --user 2000 --ulimit nproc=100 <IMAGE> <COMMAND>`
如果您透過 `sudo su` 切換到您的使用者,`rootlesskit` 將無法正確檢測 systemd。對於無法登入的使用者,您必須使用 `machinectl` 指令,它是 `systemd-container` 套件的一部分。安裝 `systemd-container` 後,使用以下指令切換到 `myuser`:
其中 `myuser@` 是您想要的使用者名稱,`@` 表示此機器。
[rootlesskit:parent] 錯誤:無法啟動子程序:fork/exec /proc/self/exe:操作不允許
此錯誤主要發生在 `/proc/sys/kernel/unprivileged_userns_clone` 的值設定為 0 時。
要解決此問題,請將 `kernel.unprivileged_userns_clone=1` 加入到 `/etc/sysctl.conf`(或 `/etc/sysctl.d`)檔案中,並執行 `sudo sysctl --system` 指令。
[rootlesskit:parent] 錯誤:無法啟動子程序:fork/exec /proc/self/exe:設備上沒有剩餘空間
此錯誤主要發生在 `/proc/sys/user/max_user_namespaces` 的值太小時。
要解決此問題,請將 `user.max_user_namespaces=28633` 加入到 `/etc/sysctl.conf`(或 `/etc/sysctl.d`)檔案中,並執行 `sudo sysctl --system` 指令。
[rootlesskit:parent] 錯誤:無法設定 UID/GID 映射:無法計算 uid/gid 映射:找不到使用者 1001 ("testuser") 的 subuid 範圍
此錯誤發生在未配置 `/etc/subuid` 和 `/etc/subgid` 時。請參閱先決條件 。
無法取得 XDG_RUNTIME_DIR
當 $XDG_RUNTIME_DIR
未設定時,會發生此錯誤。
在非 systemd 主機上,您需要建立一個目錄,然後設定路徑
**注意**
每次登出時,您都必須移除該目錄。
在 systemd 主機上,使用 pam_systemd
登入主機(見下文)。該值會自動設定為 /run/user/$UID
,並在每次登出時清除。
systemctl --user
失敗,並顯示「Failed to connect to bus: No such file or directory」(無法連線到匯流排:找不到檔案或目錄)
當您使用 sudo
從 root 使用者切換到非 root 使用者時,通常會發生此錯誤
您需要使用 pam_systemd
登入,而不是使用 sudo -iu <USERNAME>
。例如
透過圖形主控台登入 ssh <USERNAME>@localhost
machinectl shell <USERNAME>@
守護行程不會自動啟動
您需要使用 sudo loginctl enable-linger $(whoami)
來啟用守護行程自動啟動。請參閱用法 。
iptables 失敗:iptables -t nat -N DOCKER: Fatal: can't open lock file /run/xtables.lock: Permission denied(iptables 失敗:iptables -t nat -N DOCKER:致命錯誤:無法開啟鎖定檔案 /run/xtables.lock:權限被拒)
當主機上啟用 SELinux 時,舊版 Docker 可能會發生此錯誤。
此問題已在 Docker 20.10.8 中修復。舊版 Docker 的已知解決方法是執行下列指令,為 iptables
關閉 SELinux
docker: failed to register layer: Error processing tar file(exit status 1): lchown <FILE>: invalid argument(docker:無法註冊層:處理 tar 檔案時發生錯誤(結束狀態 1):lchown <檔案>:無效的引數)
當 /etc/subuid
或 /etc/subgid
中可用的項目數量不足時,會發生此錯誤。所需的項目數量因映像檔而異。但是,對於大多數映像檔來說,65,536 個項目就足夠了。請參閱先決條件 。
docker: failed to register layer: ApplyLayer exit status 1 stdout: stderr: lchown <FILE>: operation not permitted(docker:無法註冊層:ApplyLayer 結束狀態 1 標準輸出:標準錯誤:lchown <檔案>:不允許的操作)
當 ~/.local/share/docker
位於 NFS 上時,通常會發生此錯誤。
解決方法是在 ~/.config/docker/daemon.json
中指定非 NFS 的 data-root
目錄,如下所示
docker: Error response from daemon: OCI runtime create failed: ...: read unix @->/run/systemd/private: read: connection reset by peer: unknown.(docker:來自守護行程的錯誤回應:OCI 執行階段建立失敗:...:讀取 unix @->/run/systemd/private:讀取:對等端重設連線:未知。)
當使用者的 dbus 守護行程未執行時,cgroup v2 主機上通常會發生此錯誤。
要解決此問題,請執行 sudo apt-get install -y dbus-user-session
或 sudo dnf install -y dbus-daemon
,然後重新登入。
如果錯誤仍然發生,請嘗試執行 systemctl --user enable --now dbus
(不使用 sudo)。
--cpus
、--memory
和 --pids-limit
會被忽略
這是 cgroup v1 模式下的預期行為。要使用這些旗標,主機需要設定為啟用 cgroup v2。如需更多資訊,請參閱限制資源 。
本節提供無 root 模式下網路的疑難排解技巧。
RootlessKit 中的網路和連接埠驅動程式支援無 root 模式的網路。網路效能和特性取決於您使用的網路和連接埠驅動程式的組合。如果您遇到與網路相關的非預期行為或效能問題,請查看下表,其中顯示了 RootlessKit 支援的組態,以及它們之間的比較
網路驅動程式 連接埠驅動程式 網路吞吐量 連接埠吞吐量 來源 IP 傳播 無 SUID 備註 slirp4netns
內建
慢 快 ✅ ❌ ✅ 典型設定中的預設值 vpnkit
內建
慢 快 ✅ ❌ ✅ 未安裝 slirp4netns
時的預設值 slirp4netns
slirp4netns
慢 慢 ✅ ✅ pasta
隱式
慢 快 ✅ ✅ ✅ 實驗性;需要 pasta 版本 2023_12_04 或更高版本 lxc-user-nic
內建
快 ✅ 快 ✅ ❌ ❌ 實驗性 bypass4netns
bypass4netns
快 ✅ 快 ✅ ✅ ✅ **注意:**未整合到 RootlessKit,因為它需要自訂 seccomp 設定檔
有關特定網路問題的疑難排解資訊,請參閱
當特權連接埠(< 1024)被指定為主機連接埠時,docker run -p
會發生此錯誤而失敗。
當您遇到此錯誤時,請考慮改用非特權連接埠。例如,使用 8080 而不是 80。
要允許公開特權連接埠,請參閱公開特權連接埠 。
當 /proc/sys/net/ipv4/ping_group_range
設定為 1 0
時,Ping 無法運作
如需詳細資訊,請參閱路由 Ping 封包 。
這是預期行為,因為守護行程位於 RootlessKit 網路命名空間內。請改用 docker run -p
。
這是預期行為,因為守護行程位於 RootlessKit 網路命名空間內。請改用 docker run -p
。
如果已安裝 slirp4netns v0.4.0 或更高版本,則無 root 模式的 Docker 會使用slirp4netns 作為預設網路堆疊。如果未安裝 slirp4netns,Docker 會改用VPNKit 。安裝 slirp4netns 可以提高網路吞吐量。
有關 RootlessKit 網路驅動程式的更多資訊,請參閱RootlessKit 文件 。
此外,更改 MTU 值可以提高吞吐量。可以透過使用下列內容建立 ~/.config/systemd/user/docker.service.d/override.conf
來指定 MTU 值
然後重新啟動守護行程
這是因為無 root 模式的 Docker 預設使用 RootlessKit 的 內建
連接埠驅動程式,該驅動程式不支援來源 IP 傳播。要啟用來源 IP 傳播,您可以
使用 slirp4netns
RootlessKit 連接埠驅動程式 使用 pasta
RootlessKit 網路驅動程式和 隱式
連接埠驅動程式 pasta
網路驅動程式是實驗性的,但與 slirp4netns
連接埠驅動程式相比,它提供了更高的吞吐量效能。 pasta
驅動程式需要 Docker Engine 版本 25.0 或更高版本。
要變更 RootlessKit 網路組態
在 ~/.config/systemd/user/docker.service.d/override.conf
建立檔案。
根據您想要使用的組態,新增下列內容
slirp4netns
pasta
網路驅動程式和 隱式
連接埠驅動程式
重新啟動守護行程
有關 RootlessKit 網路選項的更多資訊,請參閱
進入 dockerd
命名空間
dockerd-rootless.sh
指令碼會在其自己的使用者、掛載和網路命名空間中執行 dockerd
。
為了進行除錯,您可以透過執行 nsenter -U --preserve-credentials -n -m -t $(cat $XDG_RUNTIME_DIR/docker.pid)
進入命名空間。