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 の時はコピーしないといけないから遅くなるとのこと。
上記ドキュメントにある通り、 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 を一般ユーザーに開放するの普通に嫌じゃないですか...?