Dockerコンテナー内に名前空間を作成する必要があります。そして、その一環として、内部の名前空間に/proc
privateをマウントする必要があります。これを実現するには、特定の権限でコンテナを実行する必要があることを理解していますが、最小限のセットを有効にすることをお勧めします。
これは機能します:
$ 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
フラグと-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'"'"
引用が非常に重要であるため、複数行に分割しませんでした。基本的に、子ユーザーの名前空間でunshareを実行して/proc
をマウントする前に、/proc
にあるすべてのものをマウント解除します。
Dockerは、/proc
内の多数のディレクトリとファイルを、空のtmpfsディレクトリとnullファイルである独自のディレクトリでマウントします。 /proc
のさまざまなファイルは、システム全体に適用できる値を表します。実際、/proc/kcore
を使用すると、ルートである場合にコンテナ内のカーネルメモリを読み取ることができます。これは、多くの人がコンテナが軽量であると信じたいからですVMまたは何か、多くの人を驚かせるでしょう。
カーネル(バージョン4.14以降)fs/namespace.c:mnt_already_visible
は、すでにマウントされているファイルシステムをマウントしているかどうかを確認し、そのファイルシステムに子ファイルシステムとしてマウントされているものがあり、それらのマウントにMNT_LOCKEDフラグがある場合、失敗します。 MNT_LOCKEDフラグがユーザーネームスペースを作成するときはいつでも、すべてのマウントに適用されているようです(これはカーネルのどこにあるか調べていません)。ユーザー名前空間)と非表示のものを再び表示します。
私が投稿したコマンドは、/proc/1/mountinfo
の内容にawkスクリプトを使用して、Dockerがマウントした/proc
のサブディレクトリとファイルをすべて取り出し、それらすべてをアンマウントします。これにより、/proc
ファイルシステムがネストされたユーザー名前空間に再びマウント可能になります。