Podmanにおけるユーザ名前空間の理解が曖昧なままkeep-idで誤魔化していたので自分用に整理してみました。
忙しい人向け
- ホストでもコンテナ内でもそれぞれのrootのUIDは0
- rootlessでPodmanを実行したホストユーザ(>0)はコンテナ内のroot(0)にマッピングされる
- ホスト側のroot(0)は範囲外のためマッピングされない(nobody)
- Podmanのオプションで
--userns=keep-idを使用すると実行ユーザのUIDはコンテナ内にそのまま再マッピングされる
例えば実行ユーザのUIDが1000ならばコンテナ内でも1000として扱われる。
この場合でもホストのrootはコンテナ内ではnobodyとして認識される。
マッピングルール
マッピングは/etc/subuidと/etc/subgidによってまず大枠が設定されます。
以下は/etc/subuidの例です。
user:100000:65536
これはコンテナ内の0~65535をホストの100000~165535に対応付けることを意味します。
その後、オプションに応じてホストの実行ユーザのマッピングを作成し、その分1つ後ろにシフトされます。
例えば、デフォルトでは実行ユーザはコンテナ内のroot(0)にマッピングされ、元々0と対応していた100000は1にシフトされます。それ以降も同様です。
一方でkeep-idを使用した場合、実行ユーザはコンテナ内の同じidに割り当てられます。
するとそれ以前の対応は変わらず、それ以降のみがシフトします。
例えばホストの実行ユーザUIDが1000ならば、999←→100999まではそのままで、1001←→101000から後方にシフトします。
| ホスト | コンテナ | コンテナ (--userns=keep-id) |
|---|---|---|
| root (0) | nobody | nobody |
| 実行ユーザ (仮に1000) | root (0) | 1000 |
| 100000 | 1 | root (0) |
| 100999 | 1000 | 999 |
| 101000 | 1001 | 1001 |
例
*_in_hostはホストで作成・所有者変更。
*_in_containerと*_in_container_keepidはそれぞれデフォルト・keep-id指定コンテナ内で作成・所有者変更。
- ホスト
-rw-r--r-- 1 100000 100000 0 Oct 29 10:29 100000_in_host
-rw-r--r-- 1 100999 100999 0 Oct 28 23:34 1000_in_container
-rw-r--r-- 1 101000 101000 0 Oct 29 10:44 101000_in_host
-rw-r--r-- 1 user user 0 Oct 28 23:32 root_in_container
-rw-r--r-- 1 1001 1001 0 Oct 29 10:11 1001_in_host
-rw-r--r-- 1 root root 0 Oct 28 23:14 root_in_host
-rw-r--r-- 1 user user 5 Oct 28 23:43 user_in_host
-rw-r--r-- 1 user user 0 Oct 28 23:33 user_in_container_keepid
- コンテナ ※root(0), bin(1)
-rw-r--r-- 1 bin bin 0 Oct 29 01:29 100000_in_host
-rw-r--r-- 1 1000 1000 0 Oct 28 14:34 1000_in_container
-rw-r--r-- 1 1001 1001 0 Oct 29 01:44 101000_in_host
-rw-r--r-- 1 root root 0 Oct 28 14:32 root_in_container
-rw-r--r-- 1 nobody nobody 0 Oct 29 01:11 1001_in_host
-rw-r--r-- 1 nobody nobody 0 Oct 28 14:14 root_in_host
-rw-r--r-- 1 root root 5 Oct 28 14:43 user_in_host
-rw-r--r-- 1 root root 0 Oct 28 14:33 user_in_container_keepid
- コンテナ (keep-id) ※root(0), user(1000)
-rw-r--r-- 1 root root 0 Oct 29 01:29 100000_in_host
-rw-r--r-- 1 999 ping 0 Oct 28 14:34 1000_in_container
-rw-r--r-- 1 1001 1001 0 Oct 29 01:44 101000_in_host
-rw-r--r-- 1 user user 0 Oct 28 14:32 root_in_container
-rw-r--r-- 1 nobody nobody 0 Oct 29 01:11 1001_in_host
-rw-r--r-- 1 nobody nobody 0 Oct 28 14:14 root_in_host
-rw-r--r-- 1 user user 5 Oct 28 14:43 user_in_host
-rw-r--r-- 1 user user 0 Oct 28 14:33 user_in_container_keepid
おまけ:コンテナ内ユーザを非rootにすべきか?
特にrootfulのDockerではホストのroot = コンテナ内rootなので、セキュリティの面からコンテナ内ユーザを非rootにすべきというベストプラクティスがあるらしいです。
一方でPodmanやrootlessで起動したDockerはコンテナ内rootがホストでは非root扱いなのでrootfulほど神経質になる必要はないのだろうか?と最近思い始めています。
特にホストのディレクトリをバインドマウントした場合、所有権は合わせておきたいのでコンテナ内ユーザはrootで運用したくなります。
keep-idを使えば万事解決という気もしますが、podとkeep-idを併用するとよくわからない不具合に遭遇するということが何回かあったのであまり使いたくなくなってきました。
趣味の範囲でしかコンテナは使っていないので実際の開発現場ではどのように運用しているのかがわからなくてもどかしいです。