🐳

自宅サーバを rootless に移行した際のトラブル対応

2023/01/11に公開

自宅の 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