Podmanでdevcontainerを動かしたら `mkdir: cannot create directory '/root': Permission denied`になったので対処した

事象

goなdevcontainerをPodmanで動かそうとしたら 次のようなエラーが出て失敗する。

[6760 ms] Command in container failed: mkdir -p '/root/.vscode-server/bin' && ln -snf '/vscode/vscode-server/bin/linux-x64/f1e16e1e6214d7c44d078b1f0607b2388f29d729' '/root/.vscode-server/bin/f1e16e1e6214d7c44d078b1f0607b2388f29d729'
[6760 ms] mkdir: cannot create directory '/root': Permission denied

対応

次のIssueをみたらいくつか回避方法があるようだった。

github.com

devcontainer.jsonに次を追記してdevcontainerをリビルドしたら解消した。

   "runArgs": [
        "--userns=keep-id"
    ],
    "containerUser": "vscode"

containerUserはコンテナによって合わせる必要があるかもしれない。

以上。

おまけ: オプションを調べた

なんでこの2つが必要なのかよくわかってなかった。今もよくわかってない。

"--userns=keep-id"はpodmanのオプションらしい。

https://docs.podman.io/en/latest/markdown/podman-kube-play.1.html#userns-mode

"containerUser":"vscode"だけだと、コンテナ起動まではできるようになるが、以下のようになってしまう。

vscode ➜ /workspaces/docker-bind-build $ id
uid=1002(vscode) gid=1002(vscode) groups=1002(vscode),998(nvm),999(golang)
vscode ➜ /workspaces/docker-bind-build $ ls -l
total 16
drwxr-xr-x 4 root root 4096 Jul 29 21:39 cmd
-rw-r--r-- 1 root root  722 Jul 29 21:50 Dockerfile
-rw-r--r-- 1 root root   74 Jul 29 21:54 go.mod
-rw-r--r-- 1 root root   84 Jul 29 21:47 go.sum

(docker-bind-buildっていうプロジェクト名は特に何の意味もありません。)

ファイルの所有者がrootに見える。実行ユーザはvscodeなので一致しない。編集できない。開発できない。

そこで"--userns=keep-id"を追記してdevcontainerをリビルドするとこうなった。

vscode ➜ /workspaces/docker-bind-build $ id
uid=1002(vscode) gid=1002(vscode) groups=1002(vscode),998(nvm),999(golang)
vscode ➜ /workspaces/docker-bind-build $ ls -l
total 16
drwxr-xr-x 4 vscode vscode 4096 Jul 29 21:39 cmd
-rw-r--r-- 1 vscode vscode  722 Jul 29 21:50 Dockerfile
-rw-r--r-- 1 vscode vscode   74 Jul 29 21:54 go.mod
-rw-r--r-- 1 vscode vscode   84 Jul 29 21:47 go.sum

編集できる。いい感じ。

"--userns=keep-id"だけだとおおもとのエラーになってしまった。

containerUserを"myuser"とか適当なユーザにすると、リビルドが失敗するようになってしまった。ログを見る感じ、podman runのオプションに -u myuserという感じでつけようとするので少なくともコンテナで扱えるユーザである必要がありそうだ。

うーん、コンテナ内のrootをコンテナ実行ユーザにするだけでいいはずなんじゃないんかな。devcontainerのお作法との兼ね合いがあるんだろうか。

ともかく、なぜこうなるかはよくわからないけど、動くのでヨシ!

でもこれ毎回忘れそうだな。devcontainer.jsonを作るときに勝手に追記してくれないし。

おまけ: devcontainerでpodmanを使うとは?

https://code.visualstudio.com/remote/advancedcontainers/docker-options#_podman

まず、Podmanでdevcontainerを動かすだけなら以下をsettings.jsonに足せばdockerの代わりにpodmanを使ってくれるようになる。

{
    "dev.containers.dockerComposePath": "podman-compose",
    "dev.containers.dockerPath": "podman"
}

また、上記リンクの通り、podmanに関する問題がいくつかあり、そのワークアラウンドでdevcontainer.jsonも修正が必要とあるが、その通りにやってもうまくいかなかった。