Unyablog.

のにれんのブログ

Podman で devcontainer の起動が遅い対策

Devcontainer を rootless 系のコンテナツールで利用するには podman がおすすめ(Docker rootless だと userns=keep-id がないのでコンテナ内から見たファイルが root 所有になってしまう)。

以前は userns=keep-id などをわざわざ runArgs に追加しないといけなくて面倒だったが、最近の vscode だと自動でこのフラグを付与してくれるみたいで、より使いやすくなった。

一方、podman を使っていても困ることがあり、それは大きな devcontainer になるとリビルド時の起動が遅くなること。

image のビルドが遅いのではなく、 podman によるコンテナの作成が遅い。 コンテナ作成中は podman コマンドがハングするのでステータスが謎なのも体験が悪い。

ここで、ハングしている最中に htop で確認すると storage-chown-by-maps が永遠に走っている事が分かる。これは userns=keep-id に関わる処理なのだが、 native overlay storage driver を使っていると userns=keep-id の時はコピーしないといけないから遅くなるとのこと。

github.com

github.com

上記ドキュメントにある通り、 fuse-overlayfs を利用するようにすればこの起動が遅い問題はなくなって rebuild しても一瞬で立ち上がるようになる。

永続的に設定するには ~/.config/containers/storage.conf に以下のように設定する。

[storage]
driver = "overlay"

[storage.options.overlay]
mount_program = "/usr/bin/fuse-overlayfs"

devcontainer.json の runArgs に以下のように設定しても良いが、後述の通り native と共存はできないので config として設定してしまったほうが良いと思う。

"runArgs": ["--storage-opt", "overlay.mount_program=/usr/bin/fuse-overlayfs"]

注意事項

fuse-overlayfs は native overlayfs よりも遅いので、 image build など明らかに遅くなる。

なので VSCode で devcontianer を動かすときだけ fuse-overlayfs を使うようにしたいのだが、native と fuse の共存はできないらしい。

一度 fuse-overlayfs を利用すると、その後は native overlayfs を使うように設定していても $ podman info -f '{{index .Store.GraphStatus "Native Overlay Diff"}}' の結果は false になり、fuse-overlayfs が利用され続ける。

そのため、devcontainer.json 変更や vscode 更新の際に起動が遅いのを我慢して native overlayfs を利用し続けるか、I/O が遅いのを許容して fuse-overlayfs に切り替えるかの二択になる。

普通の Docker daemon で実行すればいいって…? あはは… rootfull な Docker daemon を一般ユーザーに開放するの普通に嫌じゃないですか...?