Podman + devcontainerでtmpfsがroot所有になり非rootユーザーから書き込めない問題
Podman + devcontainerでtmpfsがroot所有になり非rootユーザーから書き込めない問題
Podmanでdevcontainerを動かしている環境で、tmpfsとしてマウントしたディレクトリがroot所有になり、コンテナ内の非rootユーザーから書き込めない問題に遭遇しました。
今回はCodex CLI用の一時ディレクトリで発生しましたが、Codexに限らず、devcontainerでtmpfsを使う場合には同じ問題が起こり得ます。
環境
環境は以下のような構成です。
Windows
└─ WSL2
└─ Podman
└─ devcontainer
└─ node user (UID 1000)
devcontainer内ではrootではなく、nodeユーザーで作業しています。
tmpfsをマウントする
devcontainerのmountsで、特定のディレクトリをtmpfsとしてマウントしていました。
"mounts": [
"type=tmpfs,target=/home/${localEnv:EXEC_USERNAME}/${localEnv:CONTAINER_AGENT_DIR}/tmp"
]
ところがコンテナ内でマウント先を確認すると、以下の状態になっていました。
ls -ld /home/node/.codex/tmp
stat -c '%U:%G %a %n' /home/node/.codex/tmp
drwxr-xr-t 2 root root ... /home/node/.codex/tmp
root:root 1755 /home/node/.codex/tmp
tmpfsのマウント先がroot:rootになっています。
この状態では、通常ユーザーであるnodeからディレクトリ内へファイルやディレクトリを作成できません。
Dockerfileでchownしても解決しない
最初に考えそうなのは、Dockerfileでマウント先をchownする方法です。
RUN chown node:node /home/node/.codex/tmp
しかし、これは今回のケースでは解決になりません。
コンテナ起動時にtmpfsがそのディレクトリの上へマウントされるため、Dockerイメージ内で設定したディレクトリの所有権はtmpfsによって隠されるためです。
Docker image
/home/node/.codex/tmp
owner: node
│
▼
コンテナ起動
│
└─ tmpfsをmount
│
▼
/home/node/.codex/tmp
owner: root
そのため、イメージを削除してリビルドしても状況は変わりません。
tmpfsにUオプションを指定する
Podmanでは、マウント時にUオプションを指定することで、コンテナ内の実行ユーザーに合わせて所有者を設定できます。
そこで、devcontainerの設定を以下のように変更しました。
変更前:
"type=tmpfs,target=/home/${localEnv:EXEC_USERNAME}/${localEnv:CONTAINER_AGENT_DIR}/tmp"
変更後:
"type=tmpfs,target=/home/${localEnv:EXEC_USERNAME}/${localEnv:CONTAINER_AGENT_DIR}/tmp,U,tmpfs-mode=0700"
Uに加えて、このディレクトリは実行ユーザーだけが利用できればよいため、tmpfs-mode=0700も指定しています。
devcontainerを再作成すると、非rootユーザーからtmpfsへ正常に書き込めるようになりました。
今回Codex CLIで発覚した理由
今回この問題に気付いたきっかけはCodex CLIでした。
Codex CLI 0.149.0を起動したところ、以下の警告が表示されました。
WARNING: proceeding, even though we could not create PATH aliases:
Permission denied (os error 13)
Codexが~/.codex/tmp配下へ必要な一時ファイルを作成しようとして、tmpfsの権限によって拒否されていました。
tmpfsのマウント設定を修正すると、この警告も解消しました。
ただし、これはCodex固有の問題というより、Codexが書き込みを行ったことでtmpfsの所有権問題が表面化したものです。
まとめ
Podman上のdevcontainerで、非rootユーザーが使用するディレクトリをtmpfsとしてマウントする場合は、単純に
type=tmpfs,target=...
とするだけでは、マウント先がroot所有になる場合があります。
その場合は、
type=tmpfs,target=...,U,tmpfs-mode=0700
のように、Uオプションと適切なmodeを指定することで解決できます。
また、tmpfsはコンテナ起動時にマウントされるため、Dockerfileでマウント先をchownしても解決しない点には注意が必要です。