自宅サーバを rootless に移行した際のトラブル対応
自宅の nerdctl + containerd 環境を rootless にした際のトラブル対応だが、 docker の場合もおおよそ似たものだろうと思う。
rootless とは
通常のままだと docker / nerdctl は root 権限で動作してしまう。 sudo usermod -aG docker <USER>
などして sudo 不要にしていても実際には sudo しているのと同じことである。
rootless にすると各ユーザごとにコンテナが起動することになる。ホストマシンでの各ユーザの権限を最高としてコンテナ内では root として扱うことができるため、例えば volume mount の中にホストマシンで root 権限を要するファイルがあった場合、コンテナからは触ることができない。
これにより脆弱性が突かれた場合でも root 権限による操作を防ぐことができる。
rootless での構築
基本ドキュメント通りで完了する。難しい操作はない。
docs/rootless.md
$ containerd-rootless-setuptool.sh install
rootless 化するに当たり必要となる依存は nerdctl からは optional であったため、存在しないとエラーとなる。(エラーメッセージが親切ではないので分かりにくいが……)
rootless でのコンテナ起動がエラーになる場合の対応
従来と同様の設定のまま rootless でコンテナを起動した際に、大したログも吐かずにエラーになることがある。
実行に root 権限を要している場合、 rootless では権限が足りずにエラーとなっていることなど、 root ユーザでないことに起因していることがある。
それぞれ以下のように対応した。
特権ポートの forward が許可されていない
特権ポート(1024 以下)の使用には通常コンテナに限らず root 権限が必要である。例えば 80:80
の port forward のコンテナは root 権限では動作するが rootless で実行するとエラーとなる。
ホスト側の特権ポートを使用しないように変更するか、以下のように rootlesskit
に特権ポートを許可する設定を追加することで対応できる。
volume mount 先の所有権が自身であるにも関わらず permission denied となる
rootless を実行するユーザが所有しているディレクトリを volume mount するとエラーとなることがある。ホストにおける一般ユーザの所有権は、コンテナ内では root として認識されるからである。
コンテナ内で root 権限を用いずに該当 volume mount へアクセスすると permission denied となる。
コンテナ内のユーザに割り振られる uid (subuid) に所有権を渡すことで対応できる。
おそらく標準で 1 ユーザの場合 /etc/subuid
は以下のようになっている。
<USER>:100000:65536
この 100000
は subuid の開始地点である。
ここから、コンテナ内の一般ユーザの uid はホストマシンからは subuid の開始地点 100000 + コンテナ内一般ユーザ 1000 - rootユーザ分1(root はホストの uid にマッピングされるため)
つまりこの場合 100999
に見える。
そのため、 $ sudo chwon 100999:100999 -R data
とすると、コンテナ内からは一般ユーザの所有ディレクトリに見えるようになる
uid mapping や subuid についてはこちらが詳しい。 Rootless, Seamless, Stateless Linux Desktop#Rootlessコンテナ内での一般ユーザ
ssh セッションを切断するとコンテナが終了してしまう
rootless の場合、 containerd 自体がユーザの systemd で動作しているため、セッションが切断されると終了してしまう。
セッションに関係なく自動で起動するように、以下を設定する必要がある。
$ sudo loginctl enable-linger <USER>
参考: サーバー起動時に非rootユーザーでsystemdを使ってサービスを立ち上げる
終わりに
まだ構築して 3 日であるが、問題なく動作しているように見える。
トラブル対応次第追加していく。
Discussion