如何在 docker 容器內的命名空間內掛載私有 /proc?
我需要在 Docker 容器中創建命名空間。作為其中的一部分,我需要將
/proc
私有掛載到內部命名空間。我意識到我必須以某些特權執行容器才能實現這一點,但我更願意啟用最小的集合。這有效:
$ sudo docker run --privileged --security-opt=seccomp=unconfined \ -it fedora:rawhide /usr/bin/unshare -Ufmp -r \ /bin/sh -c 'mount -t proc proc /proc'
這不會:
$ sudo docker run --cap-add=sys_admin --security-opt=seccomp=unconfined \ -it fedora:rawhide /usr/bin/unshare -Ufmp -r \ /bin/sh -c 'mount -t proc proc /proc' mount: /proc: cannot mount proc read-only.
因此,僅關閉 seccomp 過濾器並添加
CAP_SYS_ADMIN
是不夠的。什麼是足夠的?更新: Selinux 是問題的一部分。如果你在全域範圍內關閉 selinux 強制,它會起作用。但是,您也可以使用 關閉對特定容器的強制執行
--security-opt label:disable
,這在線上 Docker 手冊的安全配置部分中有記錄:sudo docker run --cap-add=sys_admin --security-opt label:disable \ -it fedora:rawhide /usr/bin/unshare -fmp /bin/sh -c \ 'mount --make-private / ; mount -t proc proc /proc'
但是,如果將
-U
和-r
標誌添加回unshare
. 而且,當然,添加--privileged
到 docker run 命令即使使用-U
and-r
標誌也可以正常工作。我目前正在嘗試使用核心跟踪的東西來弄清楚究竟是什麼給了我一個 EPERM。這是一個非常無用的非特定錯誤。
此命令有效:
sudo docker run --cap-add=sys_admin --security-opt label:disable -it fedora:rawhide /bin/sh -c 'for dir in $(awk '"'"'/\/proc\// { print $5; }'"'"' /proc/1/mountinfo ); do umount "$dir"; done; /usr/bin/unshare -Ufmp -r /bin/sh -c '"'"'mount --make-private / ; mount -t proc proc /proc ; ls /proc'"'"
我沒有將它分成多行,因為引用非常重要。
/proc
基本上,它在執行 unshare 並/proc
在子使用者命名空間中掛載之前解除安裝了一大堆東西。Docker 掛載了一堆目錄和文件,
/proc
其中包含自己的目錄,這些目錄是空的 tmpfs 目錄和空文件。中的各種文件/proc
表示適用於整個系統的值。事實上,/proc/kcore
如果你是 root,就可以讀取容器內的核心記憶體,因為很多人想相信容器是某種輕量級 VM 之類的東西,這會讓很多人感到驚訝。核心(從版本 4.14 開始)
fs/namespace.c:mnt_already_visible
檢查您是否正在掛載一個已經掛載的文件系統,如果該文件系統有作為子文件系統掛載的東西並且這些掛載具有 MNT_LOCKED 標誌,它會失敗。每當您創建使用者命名空間時,似乎都會將 MNT_LOCKED 標誌應用於所有掛載(我沒有追查核心中的位置),以防止您解除安裝該命名空間中的東西(因為您在“內部”獲得特權使用者命名空間)並使隱藏的東西再次可見。我發布的命令使用 awk 腳本來提取Docker 已掛載
/proc/1/mountinfo
的所有子目錄和文件,然後將它們全部解除安裝。/proc
這使得/proc
文件系統可以再次安裝在嵌套的使用者命名空間中。