🐓

Rootless Podman でも Dev Containers 拡張を使いたい!

2024/04/18に公開

前フリ

Podman とは

Podman はコンテナイメージやコンテナ実行・管理に関する規格である OCI に準拠したコンテナランタイムで、以下の特徴を持っています。

  • Docker と CLI 互換
    • 基本的に docker run ... の代わりに podman run ... と実行できる (他のサブコマンドも同様)
    • docker-compose にも対応している
  • ルート権限あり、ルート権限なしのどちらでもコンテナを実行できる
    • ルート権限なしのコンテナ実行は rootless Docker でも可能
  • デーモンなしでコンテナを実行できる
    • この部分が Docker と大きく異なる点。常時起動のプロセスを減らせるため、サーバー上の attack surface が減る

また Podman Desktop という GUI フロントエンドも提供されているため、各 OS での環境構築も容易です。
Podman Desktop は OSS なので利用制限もありません[1]

Dev Containers とは

Dev ContainersVisual Studio Code の拡張の一つで、コンテナ内のファイル操作やコマンド実行を、ローカル環境と同じ使い心地で利用できるようにする拡張です…という話を書いていたら入門記事が生えてきました。使い方などはそちらを御覧ください。

Rootless Podman では Dev Containers が動かない?

Dev Containers 拡張はデフォルトでは Docker を前提として動作しますが、rootless Podman は Docker と CLI 互換のため、同じように動くはずです。

ですが、単純な Ubuntu 用テンプレートで Dev Containers 環境を構築しようとしたところ、コンテナーの設定中にエラーが発生しました。 というダイアログとともに Dev Conatiner 環境の構築に失敗しました。

ログを見ると以下のようなメッセージが。

[2024-04-18T06:07:47.526Z] Start: Run in container: test -d '/root/.vscode-server/bin/e170252f762678dec6ca2cc69aba1570769a5d39'
[2024-04-18T06:07:47.527Z] 
[2024-04-18T06:07:47.527Z] 
[2024-04-18T06:07:47.527Z] Exit code 1
[2024-04-18T06:07:47.527Z] Stop (1 ms): Run in container: test -d '/root/.vscode-server/bin/e170252f762678dec6ca2cc69aba1570769a5d39'
[2024-04-18T06:07:47.527Z] Start: Run in container: test -d '/vscode/vscode-server/bin/linux-arm64/e170252f762678dec6ca2cc69aba1570769a5d39'
[2024-04-18T06:07:47.528Z] 
[2024-04-18T06:07:47.528Z] 
[2024-04-18T06:07:47.528Z] Stop (1 ms): Run in container: test -d '/vscode/vscode-server/bin/linux-arm64/e170252f762678dec6ca2cc69aba1570769a5d39'
[2024-04-18T06:07:47.528Z] Start: Run in container: mkdir -p '/root/.vscode-server/bin' && ln -snf '/vscode/vscode-server/bin/linux-arm64/e170252f762678dec6ca2cc69aba1570769a5d39' '/root/.vscode-server/bin/e170252f762678dec6ca2cc69aba1570769a5d39'
[2024-04-18T06:07:47.530Z] 
[2024-04-18T06:07:47.530Z] mkdir: cannot create directory '/root': Permission denied
[2024-04-18T06:07:47.530Z] Exit code 1
[2024-04-18T06:07:47.530Z] Stop (2 ms): Run in container: mkdir -p '/root/.vscode-server/bin' && ln -snf '/vscode/vscode-server/bin/linux-arm64/e170252f762678dec6ca2cc69aba1570769a5d39' '/root/.vscode-server/bin/e170252f762678dec6ca2cc69aba1570769a5d39'
[2024-04-18T06:07:47.532Z] Command in container failed: mkdir -p '/root/.vscode-server/bin' && ln -snf '/vscode/vscode-server/bin/linux-arm64/e170252f762678dec6ca2cc69aba1570769a5d39' '/root/.vscode-server/bin/e170252f762678dec6ca2cc69aba1570769a5d39'
[2024-04-18T06:07:47.532Z] mkdir: cannot create directory '/root': Permission denied
[2024-04-18T06:07:47.532Z] Exit code 1

また、このとき生成された devcontainer.json は以下でした(コメントは省略)。

{
	"name": "Ubuntu",
	"image": "mcr.microsoft.com/devcontainers/base:jammy"
}

なんでや!

VSCode はコンテナ内でも IDE としての機能を提供するため、コンテナのビルド後に ~/.vscode-remote~/.vscode-server などにソフトウェアのインストールを行います。デフォルトでは、devcontainer.json[2] 中の the user on the Docker image (大抵のコンテナイメージでは多分 root) の権限でインストール作業が行われるようです。一方で rootless Podman では、Dev Containers 初期化中には root のホームディレクトリである /root に書き込む権限がないために、環境構築に失敗するようです。

devcontainer.json には、この the user on the Docker image を変更する containerUser というパラメータがあります。Dev Containers の標準的なテンプレートのコンテナでは vscode が一般ユーザーとして追加されているため、これを containerUser として指定することで問題を解決できます。

{
  ...
  "containerUser": "vscode"
  ...
}
脚注
  1. 一方で Docker Desktop では、一定規模以上の企業などで利用する場合にはサブスクリプション契約が必要になります。皆さんはちゃんとライセンス確認して利用していますよね! ↩︎

  2. https://containers.dev/implementors/json_schema/ ↩︎

Discussion