Skip to content

Latest commit

 

History

History
852 lines (645 loc) · 50.1 KB

container-operations.md

File metadata and controls

852 lines (645 loc) · 50.1 KB

コンテナ操作ガイド

devbase のコンテナ管理機能について、ライフサイクル、並行開発、ボリューム構造、イメージ階層を解説します。

コマンド体系について: コンテナ操作は devbase project <sub> グループ(および トップレベルショートカット devbase up 等)で行います。旧 devbase container <sub> は 非推奨となり、project へのエイリアスとして警告付きで当面動作します。project では [name] を指定することで 任意のディレクトリから 対象プロジェクトを操作できます。[name] を 取るサブコマンドは位置引数の解決の「[name] を受け付けるサブコマンド」 の表を参照してください。プロジェクト一覧は devbase project list を参照 してください。詳細は CLI リファレンス: project グループ を参照。

コンテナライフサイクル

devbase のコンテナは以下のライフサイクルで管理されます。

stateDiagram-v2
    [*] --> ビルド: devbase build
    ビルド --> 停止: イメージ作成完了
    停止 --> 起動中: devbase up
    起動中 --> 起動中: devbase login
    起動中 --> 停止: devbase down
    停止 --> 起動中: devbase up

    note right of 起動中
        up 時にスナップショット自動作成
    end note
    note right of 停止
        down 時にローテーション自動実行
    end note
Loading

基本操作の流れ

# 1. コンテナイメージをビルド(初回のみ)
devbase build

# 2. コンテナを起動(自動スナップショット作成)
devbase up

# 3. コンテナにログイン
devbase login

# 4. コンテナ内で作業
# ...

# 5. コンテナから退出
exit

# 6. コンテナを停止・削除(自動ローテーション)
devbase down

自動スナップショット

コンテナのライフサイクルに連動して、スナップショットが自動管理されます。

タイミング 動作 条件
devbase up フルバックアップ or 差分追加 起動するアカウントグループの系列の最新の世代へ差分を追加。系列に世代が無いか差分が上限に達していればフルバックアップで新しい世代
devbase down 古い世代のローテーション グループ(系列)ごとに DEFAULT_MAX_GENERATIONS(3)を超えた世代と、全体の上限(9)を超えた古い世代を削除。各系列の最新の世代は残す

詳細は スナップショットガイド を参照してください。

並行開発

devbase は複数のコンテナを同時に起動し、並行開発を行うことができます。

コンテナ数の設定

プロジェクトの project.yml で scale を設定します。デフォルト値は 2 です。

version: 1
scale: 2
repos:
  - owner: your-org
    repo: my-repo

動的スケーリング

起動中のコンテナを再起動せずに、コンテナ数を変更できます。

# コンテナを3台に増やす(既存コンテナは再起動しない)
devbase project scale 3

# コンテナを1台に減らす
devbase project scale 1

# 任意のディレクトリから adminer を3台に
devbase project scale adminer 3

各コンテナへのログイン

コンテナ番号を指定してログインします。

# 1番目のコンテナにログイン
devbase login 1

# 2番目のコンテナにログイン
devbase login 2

# 3番目のコンテナにログイン
devbase login 3

並行開発のユースケース

graph LR
    subgraph ホストマシン
        A[ターミナル 1]
        B[ターミナル 2]
    end
    subgraph devbase
        C[コンテナ 1<br/>/work 専用]
        D[コンテナ 2<br/>/work 専用]
        E[共通AI設定<br/>/persistent/ai]
        F[グループ別の認証・履歴<br/>/persistent/group]
    end
    A --> C
    B --> D
    C --> E
    D --> E
    C --> F
    D --> F
Loading
  • 各コンテナは独立した /work ボリュームを持つ
  • /persistent/ai(共通の AI 資産・共有ファイル)は全コンテナで共有される
  • /persistent/group(認証情報・会話履歴)は同じアカウントグループのコンテナだけで共有される
  • /home/ubuntu 直下のうち永続化されるのは symlink 対象のみ(下記「AI 設定の永続化」参照)
  • 異なるブランチでの並行作業に便利

ボリューム構造

devbase のコンテナは 4 種類のボリュームを使用します。

ボリューム名 マウント先 共有範囲 用途
devbase_home_ubuntu /persistent/ai 全コンテナで共有 契約やテナントに紐づかない共通資産(~/.claude/plugins / skills / commands / CLAUDE.md / settings.json、.codex / .serena / .kiro、SSH 鍵、共有ファイル置き場 share)
devbase_home_{group} /persistent/group 同じアカウントグループのコンテナで共有 企業テナントに紐づくもの(Claude Code の認証と会話ログ、.gemini、Kiro CLI の .local/share/kiro-cli、gcloud / gws の設定ディレクトリ、作り直しても残るシェルの設定の置き場所 .shellrc.d)
devbase_work_{index} /work 同じ index のコンテナで共有(プロジェクト間も共有) プロジェクトのソースコード、作業ファイル
devbase_vscode-server-bin /home/ubuntu/.vscode-server/bin 全コンテナで共有(プロジェクト・グループを問わず 1 本) VS Code Server の本体(bin/<commit>)だけ。拡張機能・接続トークン・リモート側の設定は持たない

Note: devbase_home_ubuntu は /persistent/ai にマウントされます(/home/ubuntu への直接マウントは廃止)。/home/ubuntu 直下はコンテナ層(揮発)で、永続化されるのは entrypoint が /persistent/ai / /persistent/group 配下へ symlink する設定ファイルのみです。シェル履歴など symlink 対象外のファイルは再生成で失われます。

アカウントグループ

devbase_home_{group} の {group} は DEVBASE_ACCOUNT_GROUP で宣言します。 使用する Google / AWS アカウントの単位で、どのプロジェクトも projects/<name>/env での 宣言が必須です(既定の値はありません。宣言が無いと devbase up が止まります)。

# projects/<name>/env
DEVBASE_ACCOUNT_GROUP=globex

これは「acme.example で認証した gcloud を globex.example のプロジェクトが引き継がない」 ようにするための仕切りです。同じグループのコンテナは認証を共有し、違うグループのコンテナは 互いの認証に到達できません。一方で ~/.claude/plugins(238MB)のような共通資産は /persistent/ai に置かれるため、グループを増やしても重複しません。

いま自分がどのグループにいるかは、プロジェクトのディレクトリで打つ devbase status の [環境] セクションで確認できます。

[環境]
  devbase/.env            42変数 (最終更新: 2026-08-29)
  アカウントグループ          globex (devbase_home_globex / projects/web/env:1)

末尾は宣言のファイルと行です。プロジェクトの外では「なし(プロジェクトの外)」、宣言の 無いプロジェクトでは (設定エラー) と宣言の書き方が出ます。

グループ名には次のものが使えません。devbase up の前にエラーになります。

使えない名前 理由
^[a-zA-Z0-9][a-zA-Z0-9._-]*$ に合わないもの Docker のボリューム名にできない
ubuntu 共通ボリューム devbase_home_ubuntu と同名になる
default 旧既定のボリューム devbase_home_default と同名になる(予約語)
数字だけの名前(1 / 042) インスタンス番号のボリューム devbase_home_<index> と同名になる

Google 認証の具体的な手順は Google 認証ガイド を参照してください。

VS Code Server の永続化

VS Code を attach すると、コンテナ内の ~/.vscode-server に VS Code Server が入ります。 ボリュームに置くのは本体(bin/<commit>、1 版で約 0.6GB)だけで、全コンテナ共通の 1 本 devbase_vscode-server-bin を ~/.vscode-server/bin にマウントします。

本体を共有するのは、版ごとに中身が変わらず、プロジェクトとインスタンスの数だけ同じ版を 重ねて持つ理由が無いためです。どれか 1 つのコンテナで一度取れば、ほかのコンテナの attach は本体を 取り直しません。

置き場 どこにあるか 消えるとき
bin/(本体) 共通のボリューム devbase_vscode-server-bin コンテナの起動の片付けが古い版を消す(下記)
extensions/・extensionsCache/・data/ など bin/ 以外 コンテナの書き込みレイヤー(ボリュームではない) devbase up の作り直し(down → up)。docker restart と端末の再起動では残る
拡張のキャッシュと、新しい版の本体(Dev Containers が置く) Dev Containers の共有の置き場 vscode(/vscode) 拡張は起動の後の処理が拡張ごとに新しい 3 版を残して消す。本体は Dev Containers が新しい 9 版を残して消す

dev コンテナには、名前 vscode のボリュームも /vscode に付きます。Dev Containers 拡張は、このボリュームが 付いたコンテナでは拡張のキャッシュをこの中に持ち、VS Code を動かしている手元の端末のキャッシュを使いません。 ボリュームは docker ホストごとにあるので、arm64 の端末(Mac など)で入った拡張が x86_64 のサーバーのコンテナへ 送られることはありません。新しい版の本体も Dev Containers がこの中(/vscode/vscode-server/bin/<build>/<commit>)に置き、 ~/.vscode-server/bin/<commit> にはそこへのリンクを張ります。

devbase up でコンテナを作り直すたびに、次のものが消えます。

  • 手で入れた拡張機能。Dev Containers の既定の拡張機能は、 作り直しの後の最初の attach で入り直します
  • リモート側の設定(data/Machine/settings.json)のうち、手で入れたもの。window.title は devbase up が毎回書き直します
  • ローカル履歴(data/User/History)と、拡張機能がリモート側に保存する状態 (data/User/globalStorage・data/User/workspaceStorage。Copilot Chat など)
  • ログ(data/logs)。消えるため溜まりません
  • 接続トークンと .devport。次のサーバーの起動で作り直されます

bin/ 以外がコンテナごとに分かれているため、窓のタイトルと窓の再接続(ウィンドウの再読み込み)は コンテナごとに働きます。

本体の旧版の片付け

VS Code を更新するたびに bin/ へ新しい版が足されます。コンテナの起動(entrypoint)が毎回 bin/ を片付け、次のものを消します。

  • 新しい順に 5 版を残し、それより古い版。順は各版の product.json の更新時刻で決めます
  • 複数の窓が同じ版を同時に展開したときに、版のディレクトリの中に入れ子で残った本体 (bin/<commit>/vscode-server-linux-<arch>/)
  • 60 分より前に始まって終わらなかった展開の途中のディレクトリ(bin/<commit>_<数字>)

消せないものがあっても起動は止まらず、WARNING: VS Code Server の片付けで消せなかった: <パス> の行が出ます。片付けは base と派生イメージを建て直した後から効きます。それまでは bin/ に 版が溜まりますが、共通の 1 本なので、プロジェクトとインスタンスの数だけ重なりません。

  • プロジェクトが compose.yml で ~/.vscode-server か ~/.vscode-server/bin を自分で マウントしている場合、devbase は何も足しません。~/.vscode-server/data など下の別のパス だけをマウントしているときは、共通のボリュームを bin に足します
  • スナップショット(devbase snapshot)の対象外です。失っても attach し直せば再取得されます
  • 空のボリュームは root の所有で付きます。コンテナの起動と、devbase up / scale / project post-start の起動の後の処理が、~/.vscode-server/bin を開発ユーザーが書ける形に 揃えます(建て直す前のイメージでも attach できます)

以前の VS Code Server ボリュームから移る

以前の devbase は ~/.vscode-server を丸ごと、コンテナ 1 つに 1 本のボリューム devbase_vscode_{project}_{index} に置いていました。今の devbase はこれを付けず、中身も 引き継ぎません。移った後の最初の attach で本体(約 215MB、約 55 秒)を取り直し、拡張機能は 入れ直しになります。

以前のボリュームが残っている間、devbase up の最後に名前と消すコマンドが出ます。devbase は 消しません。下の「使わなくなった VS Code Server ボリュームを消す」の手順で消してください。

ボリュームの永続性

  • ボリュームは devbase down でもコンテナが削除されても保持されます
  • コンテナの再起動(devbase up)で同じボリュームが再マウントされます
  • ボリュームを明示的に削除するには docker volume rm を使用します

Warning: devbase_work_{index} は COMPOSE_PROJECT_NAME の接頭辞が付かない external ボリュームです。同じ index(コンテナ 1 なら devbase_work_1)を使う限り 別プロジェクトからも同じ実体を参照するため、docker volume rm devbase_work_1 は停止中の他プロジェクトの作業ファイルまで削除します。削除前に docker ps -a --filter volume=devbase_work_1 で利用コンテナを確認してください。

ボリュームの確認

# Docker ボリュームの一覧
docker volume ls | grep devbase

# 特定ボリュームの詳細
docker volume inspect devbase_home_ubuntu

使わなくなった VS Code Server ボリュームを消す

以前の形式の devbase_vscode_{project}_{index} は、今の devbase では使いません。自動では 消えないため、手で削除します。1 本で数 GB を使うことがあります。

# 一覧(共通の devbase_vscode-server-bin は出ない)
docker volume ls --filter name=devbase_vscode_ --format '{{.Name}}'
docker system df -v | grep devbase_vscode_

# 要るデータを退避する(下の注意を参照。カレントディレクトリへ tar で書き出す)
docker run --rm -v devbase_vscode_<project>_1:/from:ro -v "$PWD":/to alpine \
  tar czf /to/vscode_<project>_1.tgz -C /from .

# 使用中のコンテナが無いことを確認してから削除する
docker ps -a --filter volume=devbase_vscode_<project>_1
docker volume rm devbase_vscode_<project>_1

Warning: 以前の形式のボリュームは ~/.vscode-server 全体を持っています。削除すると、 以前の VS Code Server の本体と拡張機能(extensions/)に加え、次のものも戻せなくなります。

  • リモートの設定(data/Machine/settings.json)
  • ローカル履歴(data/User/History/)
  • 拡張機能が保存した状態(data/User/globalStorage/・data/User/workspaceStorage/)

要るものがあれば、削除の前に上の tar の行で退避してください。戻すときは、展開した中の要る ファイルだけを docker cp でコンテナの ~/.vscode-server/ の同じ場所へ写します。AI 設定 (~/.claude など)は別のボリュームにあるため、この削除では消えません。

devbase up の案内に出る docker volume rm … の行は、退避が要らないと確かめた後に打ってください。 以前の devbase で作ったコンテナが付けているボリュームは docker volume rm が 拒否します。そのプロジェクトで devbase up を打ってコンテナを作り直した後に消してください。

共通の devbase_vscode-server-bin は消さなくて構いません。消したときは、次の attach で本体を 取り直します。

Warning: devbase_home_ubuntu ボリューム(/persistent/ai、および symlink 経由でアクセスする ~/.claude/plugins / ~/share 等)は全プロジェクトで共有されます。ここにプロジェクト固有のファイルを置くと、他のプロジェクトにも影響します。プロジェクト固有のファイルは /work に配置してください。

AI 設定の永続化

AI CLI ツールの設定や認証情報は、コンテナを再生成しても保持されるよう 2 つのボリュームに永続化されます。

仕組みは symlink です。コンテナ起動時、entrypoint(containers/base/entrypoint.sh)が 以下の各エントリについて symlink を作成します。

全コンテナ共通(/persistent/ai)

エントリ 内容
.codex Codex CLI の設定(ChatGPT アカウントで分離済み)
.serena Serena MCP の設定
.kiro Kiro CLI の設定(AWS 側で分離済み)
.ssh SSH 鍵
share 全コンテナ共有のファイル置き場(任意用途)
.claude/plugins .claude/skills .claude/commands .claude/CLAUDE.md .claude/settings.json Claude Code の共通資産

アカウントグループ単位(/persistent/group)

エントリ 内容
.claude.json Claude Code の設定(oauthAccount を含む)
.claude Claude Code の認証・会話ログ・セッション状態(上表の共通資産を除くすべて)
.gemini Gemini CLI と Antigravity CLI の設定(vertex-ai は GCP プロジェクトに紐づく。Antigravity CLI は .gemini/antigravity-cli/ 配下を使う)
.local/share/kiro-cli Kiro CLI 2.x の認証状態・実行データ
.shellrc.d 対話シェルが起動時に読む *.sh の置き場所。パスは DEVBASE_SHELLRC_DIR が示す。反映には devbase build base --no-cache が要る(作り直しても残るシェルの設定)

~/.claude は /persistent/group/.claude への symlink で、その配下の既定はグループ側です。 共通資産だけがその中から /persistent/ai/.claude/<name> へ張り直されます。既定をグループ側に 倒しているのは、Claude Code が projects / sessions / tasks のようなディレクトリを随時作るため、 永続化するものを列挙する方式だと列挙漏れが黙って揮発するからです。

$ readlink -f ~/.claude              # グループ側
/persistent/group/.claude
$ readlink -f ~/.claude/plugins      # 共通側(どのグループから見ても同じ実体)
/persistent/ai/.claude/plugins
  • /persistent/ai は全コンテナ共通の devbase_home_ubuntu ボリュームなので、どのコンテナからも同じ実体を参照します(例: ~/share は全コンテナで共有)。
  • /persistent/group は devbase_home_{group} で、同じアカウントグループのコンテナだけが同じ実体を参照します。
  • symlink 対象外のホーム配下ファイル(シェル履歴など)はコンテナ層に置かれ、再生成で失われます。永続化したいものは /persistent/ai / /persistent/group 配下(= 上記 symlink 先)か /work に置いてください。

共通の設定が通常のファイルに置き換わったとき(控え)

~/.claude/settings.json と ~/.claude/CLAUDE.md は共通側を指す symlink です。ツールが「一時ファイルへ書いて rename する」形で保存すると、symlink そのものがグループ側の通常のファイルに置き換わります。

次の起動で entrypoint がこれを見つけると、中身を共通側の実体と比べます。

  • 同じなら、何も残さずに symlink を張り直します

  • 違うなら、張り直す前に同じ .claude の下へ控えを残します。控えの名前は <名前>.replaced-<UTC の時刻> (例: /persistent/group/.claude/settings.json.replaced-20261002T190116Z)で、中身・所有者・権限は置き換わって いたファイルと同じです。同じ中身の控えが既にあれば、新しい控えは作りません

  • 控えを残したときは、起動の記録(docker logs <コンテナ>)に次の行が出ます

    WARNING: 共有のリンクが通常のファイルに置き換わっていたため、中身を控えに残して張り直す: <控えのパス>
    
  • 控えを作れない(書き込めないなど)ときは、ファイルを消さずに残し、そのリンクだけ張り直しません。起動の記録に WARNING: 共有のリンクが通常のファイルに置き換わっているが、控えに残せないため張り直さずに残す: <パス> が出ます。 書き込めるようになった次の起動で控えを作って張り直します

控えの中身は共通側へ自動では取り込みません。あるグループで書いた設定が確認なしにすべてのグループへ広がらない ようにするためです。戻すかは次の手順で決めます。

  1. docker logs <コンテナ> の WARNING: の行か、ls ~/.claude/*.replaced-* で控えを見つける
  2. diff ~/.claude/settings.json.replaced-<時刻> ~/.claude/settings.json で、控えと今の共通の設定の違いを見る
  3. 残したい違いだけを ~/.claude/settings.json へ書く。このパスは共通側を指すため、すべてのグループに効きます。 控えのファイルを mv で ~/.claude/settings.json の位置へ置かないでください(共通の設定が再び通常のファイルに 置き換わります)
  4. 要らなくなった控えを消す(entrypoint は控えを消しません)

CLAUDE.md の控え(CLAUDE.md.replaced-<時刻>)も同じ手順で戻します。反映には base イメージの建て直しが要ります。 建て直す前のイメージのコンテナは、控えを残さずに消して張り直します。

グループのボリュームの初期状態

グループのボリュームへ初めて付けたコンテナでは、/persistent/group の分類 B の設定 (.claude.json / 認証 / 会話ログ / .gemini / gcloud / gws)は空のプレースホルダです。 /persistent/ai からの取り込みは行わないため、新しいグループ(例: personal)では claude・gh・gcloud などのログインを取り直します。グループの宣言が必須になる前に使っていた devbase_home_default の中身は、devbase project migrate-volume --to <group> で移します (default からの移行)。

コンテナは DEVBASE_ACCOUNT_GROUP が渡らないと起動しません(entrypoint がリンクを張る前に 0 でない終了コードで止まります)。devbase up はプロジェクトの宣言の値を必ず渡します。 entrypoint の変更はイメージを作り直すまで効かないため、devbase を更新したら devbase build --no-cache を打ってください。

起動ログの 1 行で、どのグループとしてどのアカウントで動いているかを確認できます。

Account group: globex (gcloud account: someone@globex.example, CLOUDSDK_CONFIG: /persistent/group/gcloud)
  • share 配下に置いた VS Code ワークスペースファイルは DEVBASE_WORKSPACE で開けます(リポジトリ 1 件の構成のみ。環境変数 参照)。

Note: symlink 対象は entrypoint にビルド時 COPY で焼き込まれます。エントリを増減した場合は イメージの再ビルドが必要です(devbase up 単体では反映されない場合があります。CLI リファレンス: project グループ の devbase project up の注記参照)。

gcloud / gws の設定はどこにあるか

gcloud と gws は symlink ではなく 環境変数で設定ディレクトリごと差し替えています。

変数 向き先 入るもの
CLOUDSDK_CONFIG /persistent/group/gcloud credentials.db / access_tokens.db / legacy_credentials/ / configurations/ / application_default_credentials.json(ADC ファイル)
GOOGLE_WORKSPACE_CLI_CONFIG_DIR /persistent/group/gws credentials.enc / .encryption_key

CLOUDSDK_CONFIG は gcloud CLI 専用の仕組みではなく google.auth の探索経路そのものなので、 BigQuery クライアント等のライブラリも同じ場所を見ます。

Warning: この差し替えにより、~/.config/gcloud は gcloud の設定ディレクトリでは なくなりました。鍵モード(GCP_AUTH_MODE=key)で書き出されるサービスアカウント鍵の 置き場でしかなく、コンテナ層(揮発)に残ります。したがって鍵は毎起動 env から書き直され、 永続領域には残りません。設定を見たいときは $CLOUDSDK_CONFIG を参照してください。

認証モードの切り替えは 環境変数ガイド の GCP_AUTH_MODE、 実際の認証手順は Google 認証ガイド を参照してください。

Warning: gcloud は並行実行を想定していません(公式ドキュメント: "Parallel execution of multiple gcloud CLI commands is not supported.")。credentials.db は SQLite なので、 同じアカウントグループの複数コンテナが同時に gcloud を叩くと database is locked が 出ることがあります。恒久対策は取っていないので、その場合は少し待って再実行してください。

コンテナイメージ階層

devbase のコンテナイメージは用途に応じた階層構造になっています。

graph TD
    A[Ubuntu 26.04] --> B[base]
    B --> C[general]
    B --> G[go]
    B --> J[browser]
    B --> D[php]
    B --> I[php85]
    B --> E[latex]
    A --> H[snapshot]

    style A fill:#f0f0f0
    style B fill:#e8e8f4
    style C fill:#e8f4e8
    style G fill:#f4f0e8
    style H fill:#f4e8e8
Loading

イメージの詳細

イメージ ベース 主な内容 用途
base Ubuntu 26.04 Docker CLI、Python 3、AWS CLI、gcloud、Node.js(LTS)、AI CLI、日本語フォント、PDF / OOXML の道具、shellcheck 汎用開発環境の土台
general base base のまま(道具を足さない) 汎用開発環境
php base PHP 8.5、Composer、MySQL Shell PHP 8.5 系 開発
php85 base PHP 8.5、Composer、MySQL Shell PHP 8.5 系 開発
latex base LaTeX 文書作成
go base Go 開発環境 Go 開発
browser base Playwright の Chromium とその依存パッケージ、Noto CJK の追加の太さ(Thin〜Black) ブラウザの操作、HTML の PDF・スクリーンショット
snapshot Ubuntu 26.04 zstd のみ(約 80MB) スナップショット専用

派生イメージはどれも base を継ぐため、AWS CLI・gcloud・Node.js・AI CLI はどの派生イメージでも 使えます。terraform はどの標準イメージにも入っていません(入れ方は ブラウザ・追加の太さのフォント・terraform を使う)。 containers/ にはこのほか、特定のプロジェクト用のイメージ(bi-tools / trygroup)があり、 どちらも base を継ぎます。

文字の描画と、文書を扱う道具(base 以降)

base イメージは、文字を描くときの既定を日本語にしています。総称ファミリ(sans-serif / sans / serif / monospace)と、イメージに無い書体名(Meiryo / Yu Gothic / MS PGothic / Noto Sans JP など)は、いずれも Noto CJK の JP フェイスへ解決されます。 fontconfig は Chromium / Playwright のスクリーンショット、PDF の生成、画像の生成がすべて 参照するため、日本語を含むページを撮っても日本語の字形で写ります。base が持つ Noto CJK は 標準の太さ(Regular・Bold)です。追加の太さ(Thin・Light・Medium・Black など)は browser の イメージにあります。

指定 解決先
sans-serif / sans Noto Sans CJK JP
serif Noto Serif CJK JP
monospace Noto Sans Mono CJK JP
Arial / Times New Roman / Courier New Liberation Sans / Serif / Mono(metric 互換)
Calibri / Cambria Carlito / Caladea(metric 互換)
sans-serif:lang=zh-cn など、言語を明示した指定 その言語の、同じ様式のフェイス(SC / KR)

言語を明示しない中国語は、日本語の字形で描かれます。 lang を伴わない sans-serif は どちらかの言語を選ばざるをえないためで、意図した振る舞いです。中国語・韓国語で描きたい ときは lang=zh-cn / lang=ko を明示するか、書体を名指ししてください。

設定は /etc/fonts/local.conf(containers/base/fonts-local.conf)にあります。個人の設定 ~/.config/fontconfig/fonts.conf はこれより先に読まれるため、コンテナの中で上書きできます。

文書を扱う道具も base に入っています。

道具 用途
pdftoppm / pdftocairo PDF を画像(PNG / JPEG / SVG)にする
pdfinfo / pdffonts PDF のページ数・寸法・埋め込みフォントを調べる
python3 -c "import PIL" 画像の読み書き・変換(Pillow)
python3 -c "import lxml, defusedxml" OOXML(.docx / .xlsx / .pptx)を壊さずに読み書きする

LibreOffice と pip は入っていません。 LibreOffice は展開 372〜459MB で base の規律に 見合わないため入れていません。Python パッケージが要るときは uv / uvx を使ってください。

base にはブラウザが入っていません。Playwright(@playwright/test)は入っていますが、 Chromium とその依存パッケージは browser のイメージにあります。base 系のイメージ(base・ general・php など)で Playwright の Chromium を起動すると、npx playwright install を 打つよう示して止まります。使い方は次の節を見てください。

これらは devbase build base --no-cache で base を建て直すと反映されます。 devbase up だけでは反映されません。派生イメージ(general・browser など)を使っている プロジェクトは、その派生イメージも建て直し、devbase down → devbase up でコンテナを 作り直してください。 devbase rebuild では建て直りません。 devbase build --expires=7 のシノニムのため、 期限内はビルドそのものを飛ばします。

規則の中身と、その置き場所を動かせない理由は base イメージの文字の描画と、文書を扱う道具 にあります。

ブラウザ・追加の太さのフォント・terraform を使う

base は、すべての利用者が使う道具だけを持ちます。次のものは base にありません。

要るもの 使い方
ブラウザ(Playwright の Chromium とその依存パッケージ) browser のイメージを選ぶ
Noto CJK の追加の太さ(fonts-noto-cjk-extra) browser のイメージを選ぶ
terraform プロジェクトの Dockerfile かフックで入れる

browser のイメージを選ぶ。 プロジェクトの compose.yml の dev サービスで、build.context を containers/browser にします。ほかの派生イメージと同じく、devbase build は base を先に建ててから このイメージを建てます。プロジェクトの Dockerfile が派生イメージを FROM に取るときも、devbase build は containers/<名前>/Dockerfile の FROM devbase-* をたどり、下の段から順に建てます。

services:
  dev:
    build:
      context: ${DEVBASE_ROOT}/containers/browser/

建て直した直後から、ネットワーク無しで Chromium を起動し、日本語のページを PDF や スクリーンショットにできます。置き場は /opt/ms-playwright(環境変数 PLAYWRIGHT_BROWSERS_PATH)です。

システムの Chrome(google-chrome-stable、/usr/bin/google-chrome)はどのイメージにも入っていません。 Playwright から使うときは何も変えずに Chromium が起動します。Playwright を介さずにブラウザの 実行ファイルを渡す道具には、browser のイメージで次のコマンドが出す Playwright の Chromium の パスを渡してください。

NODE_PATH="$(npm root -g)" node -e "console.log(require('@playwright/test').chromium.executablePath())"

php などほかの派生イメージの道具も要るとき。 browser のイメージには PHP などの道具が ありません。次の道筋から、プロジェクトの道具立てに合うものを選びます。

道筋 すること 気をつけること
browser のイメージを選ぶ 上の build.context に替える 元の派生イメージの道具が無くなる
プロジェクトの Dockerfile で足す FROM devbase-php:latest などの上で、利用者 ubuntu が npx playwright install --with-deps chromium を打つ devbase build は継承の連なりを下の段から建てる(devbase-base → devbase-php → プロジェクト)。たどる途中の containers/<名前>/ が無いときは、何も建てずに止まる
道具の起動引数でブラウザの場所を渡す MCP の起動引数などで、上の 2 つのどちらかで用意した Chromium の実行ファイルを指させる ブラウザと依存パッケージは、ほかの 2 つの道筋で用意する

@playwright/mcp や chrome-devtools-mcp は、既定でシステムの Chrome を探すことがあります。 選んだ道筋で、実際に起動できることを確かめてください。

コンテナの中で一時的に取得する。 base 系のコンテナでも、次のコマンドで Chromium と依存 パッケージを取得できます。コンテナを作り直すと消え、取得のたびに数百 MB をネットワークから取ります。

npx playwright install --with-deps chromium

terraform を入れる。 プロジェクトの Dockerfile(root の RUN)か、コンテナ起動時のフックで HashiCorp の apt の取得元を足して入れます。

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install -y terraform

Bash の静的検査(base 以降)

base イメージには ShellCheck(shellcheck)が入っています。 コンテナの中で Bash スクリプトを検査できます。

shellcheck path/to/script.sh

指摘は SC2086 のような番号つきで出て、指摘があれば終了コード 1 で終わります。 bash-language-server などの言語サーバは Bash の診断を shellcheck に任せているため、 コンテナの中で言語サーバを動かすときもこれが使われます(言語サーバ自体は base に入っていません)。

版は固定しておらず、base を建てた時点の Ubuntu のアーカイブの版が入ります。 containers/snapshot は base を継がないため入っていません。 置き場所・入れ損ないの止め方・版の扱いの仕様は base イメージの Bash の静的検査(shellcheck) にあります。

devbase build base --no-cache で base を建て直すと反映されます。 devbase up だけでは 反映されません。派生イメージ(general / php など)を使っているプロジェクトは、その 派生イメージも建て直し、稼働中のコンテナは devbase down → devbase up で作り直して ください。devbase rebuild では建て直りません。

AI CLI エイリアス

base イメージ以降(snapshot を除くすべての標準イメージ)のコンテナ内では、以下の AI CLI ツールがエイリアスとして利用可能です。

エイリアス ツール モード 説明
claude Claude Code skip-permissions Anthropic の AI コーディングアシスタント
claudb Claude Code (AWS Bedrock) Opus 4.6 / us-west-2 AWS Bedrock 経由の Claude
gemini Gemini CLI yolo mode Google の AI アシスタント
codex Codex CLI bypass-approvals OpenAI の AI コーディングツール
kiro Kiro CLI trust-all-tools AWS の AI アシスタント
agy Antigravity CLI dangerously-skip-permissions Google の AI コーディングエージェント
# コンテナ内での使用例
claude "このコードをレビューして"
gemini "テストを書いて"
codex "リファクタリングして"

AI CLI の起動定義

コンテナの対話シェルでは、各 AI CLI が確認プロンプトを省くオプション付きで起動します。 定義は /etc/devbase/ai-cli-aliases.sh にあり、~/.bashrc から読み込まれます。

コマンド 起動するもの
claude claude --dangerously-skip-permissions
claudb claude --dangerously-skip-permissions(Amazon Bedrock 経由。CLAUDE_CODE_USE_BEDROCK=1 / AWS_REGION=us-west-2 を前置)
gemini gemini --yolo
codex codex --dangerously-bypass-approvals-and-sandbox
kiro kiro-cli chat --trust-all-tools
agy agy --dangerously-skip-permissions

引数はそのまま後ろへ渡ります(gemini "テストを書いて" は gemini --yolo "テストを書いて")。 素の CLI を使いたいときは command gemini ... のように command を前置します。

gemini の認証方式

起動定義は認証方式を決めません。 環境変数 GOOGLE_GENAI_USE_VERTEXAI で選びます。

設定 経路
GOOGLE_GENAI_USE_VERTEXAI=true Vertex AI(GOOGLE_CLOUD_PROJECT と ADC が要る)
未設定・空 ~/.gemini/settings.json の selectedType に従う(oauth-personal など)

Vertex AI を既定にするなら共通の設定へ入れます。

devbase env set GOOGLE_GENAI_USE_VERTEXAI=true

Vertex AI を使わないプロジェクト(別会社のアカウントで OAuth ログインするなど)は、 projects/<name>/env で空にして共通の値を打ち消します。GOOGLE_CLOUD_PROJECT と同じやり方です。

GOOGLE_GENAI_USE_VERTEXAI=
GOOGLE_CLOUD_PROJECT=

GOOGLE_CLOUD_PROJECT は認証方式を選ぶ変数ではありません。 gcloud や BigQuery でも使う プロジェクト指定なので、OAuth を使いながら別の用途で設定していても Vertex へは切り替わりません。

~/.gemini はアカウントグループのボリューム(/persistent/group/.gemini)にあるため、 OAuth のログインはコンテナを作り直しても残ります。

作り直しても残るシェルの設定

~/.bashrc はイメージの中にあるため、書き足した alias や関数はコンテナを作り直すと消えます。 作り直しても残したい設定は、置き場所 ~/.shellrc.d/ へ *.sh のファイルとして置きます。

cat > ~/.shellrc.d/my-aliases.sh <<'SH'
alias ll='ls -alF'
SH

置いたファイルは、次に開く対話シェル(devbase login / tmux の窓 / VS Code の端末)から効きます。

項目 振る舞い
実体 /persistent/group/.shellrc.d/。同じアカウントグループのコンテナすべてで同じ設定が効き、別のグループには効かない
パス 環境変数 DEVBASE_SHELLRC_DIR(/home/ubuntu/.shellrc.d)。docker exec の非対話の処理からも見える。設定を足すツールはこの変数の指す先へ 1 ファイル置き、~/.bashrc を書き換えない
読まれるもの 置き場所の直下の、名前が .sh で終わるファイル。サブディレクトリの中・. で始まる名前・他の拡張子は読まない
読む順 ファイル名の昇順。AI CLI の起動定義の後に読むので、同じ名前の alias(claude など)は置き場所の定義が勝つ
読まれる時点 対話の bash の起動時だけ。スクリプトや docker exec ... bash -c などの非対話の処理では読まれない
誤り ファイルの中の構文・実行のエラーは標準エラーに出て、次のファイルへ進む。読み取り権限の無いファイル・リンク切れの symlink は、何も出さずに飛ばす

置くファイルの作法:

  • 1 つの用途につき 1 ファイルにし、<名前>.sh とします。順序を決めたいときは 10- のような数字を前に付けます
  • 何度読まれても同じ結果になるように書きます。exit は書きません(対話シェルが終わります)。標準出力へは何も出しません
  • devbase は置き場所へ何も書きません。置いたものを消すのは置いた側です
  • DEVBASE_SHELLRC_DIR を別の場所へ向けると、読み込みもそちらへ移ります。ただし向けた先は永続化されません

反映には devbase build base --no-cache が要ります。 devbase up だけでは反映されません (読み込みの 1 行と DEVBASE_SHELLRC_DIR はイメージの中にあります)。派生イメージを使う プロジェクトはその派生イメージも建て直し、稼働中のコンテナは devbase down → devbase up で 作り直してください。zsh(base には入っていません)は対象外です。

読む先の決め方・読み込みの前後で保つ条件・エラーの扱いの仕様は 作り直しても残るシェルの設定(~/.shellrc.d)にあります。

tmux(ターミナル)の既定設定

コンテナ内の tmux には、devbase 共通の既定設定 /etc/tmux.conf が入っています (実体は containers/base/tmux.conf)。tmux は起動すると端末の代替画面へ切り替わるため、 出力履歴は VS Code のスクロールバックではなく tmux 自身のバッファに入ります。素の tmux は 履歴 2000 行・マウス無効なので、この履歴に実質手が届きません。既定設定はそこを埋めます。

設定 値 理由
mouse on ホイールを転がすと copy-mode に入り、履歴を遡れる
history-limit 100000 既定の 2000 行はビルドログ 1 回で流れ切る
focus-events on 端末のフォーカス通知を中のアプリへ渡す。Claude Code の完了通知が正しく出し分けられる
default-terminal tmux-256color 端末種別の固定
terminal-overrides ,xterm-256color:Tc を追記 VS Code の統合ターミナルへ 24bit 色を通す
terminal-features ,xterm-256color:hyperlinks を追記 OSC 8 のハイパーリンクを外側の端末へ渡す。宣言しないと tmux がリンクを捨て、Claude Code などが出す URL がクリックできない

基本操作

操作 キー
スクロール マウスホイール(自動で copy-mode に入る)
範囲選択 ドラッグ(ボタンを離しても選択を保持)
コピー 選択中に Ctrl+C(クリップボードへ入れて copy-mode を抜ける)
選択解除 q
copy-mode に入る Ctrl-b [
履歴内を検索 copy-mode 中に Ctrl-r(上方向)/Ctrl-s(下方向)
copy-mode を抜ける q
ペインをまたいで選択 Shift + ドラッグ(VS Code のネイティブ選択に切り替わる)

ドラッグ終了後も選択範囲が残ります。Ctrl+C を押すと tmux が OSC 52 を送出し、VS Code の クリップボードへ書き込んで copy-mode を抜けます。コピーせず選択を解除する場合は q を 押します。

上表の copy-mode のキーは tmux の mode-keys に従います。既定は emacs ですが、tmux は EDITOR / VISUAL に vi を含む値が入っていると vi へ切り替えるため、その場合の検索は /(下方向)と ?(上方向)になります。

個人設定で上書きする

tmux は /etc/tmux.conf を読んでから ~/.tmux.conf を読み、同じオプションは後から読んだ ~/.tmux.conf が勝ちます。既定値を変えたい場合は ~/.tmux.conf に書いてください。

# 例: ホイールを tmux に渡さず、端末側のスクロールに戻す
echo 'set -g mouse off' >> ~/.tmux.conf
tmux source-file ~/.tmux.conf   # 実行中のセッションを保ったまま反映する

Note: source-file はセッションや配下のプロセスを終了せずに設定を読み直し、mouse のような オプションは即時に反映されます。ただし history-limit は新しく作る pane から適用され、既存の pane は作成時の値を保持します。既存 pane にも効かせたい場合は、その pane を作り直してください。

Note: ~/.tmux.conf は永続化の対象外です(/persistent/ai へ symlink されるのは ~/.claude などの AI 設定のみ)。コンテナを作り直すと消えるため、残したい設定は ~/share 配下など永続領域へ置いてコピーしてください。

Note: /etc/tmux.conf はイメージに焼き込まれています。設定を変更した場合の反映には devbase container build によるイメージの再ビルドと、コンテナの作り直しが必要です。

セッションが増えてしまったときの整理(tmux-first / tmux-clean)は 環境変数ガイド を参照してください。

コンテナの状態確認

プロセス一覧

# 起動中のコンテナを表示
devbase ps

# 停止中のコンテナも含めて表示
devbase ps -a

ログの確認

# 最新のログを表示
devbase project logs

# リアルタイムでログを追跡
devbase project logs -f

# 末尾100行のみ追跡
devbase project logs -f --tail 100

プロジェクト一覧

# 階層メニュー TUI を起動(TTY ではこれがデフォルト)
devbase list

# 選択せず NAME / PLUGIN / STATUS の一覧表示のみ
devbase list --no-interactive   # --plain / -P も同義

TTY(端末)では devbase list はデフォルトで階層メニュー TUI になり、 プロジェクトを選んで起動・操作(up / down / login / ps / logs / scale / build / rebuild)できるほか、画面最下部の常設メニュー(環境変数 / プラグイン / スナップショット / ステータス)へ ←→ キーで移動して各管理操作を実行できます。 パイプ・リダイレクト・CI などの非 TTY 環境では自動的に一覧表示のみに フォールバックします。画面構成とキー操作の詳細は CLI リファレンス: project グループ を参照してください。

devbase project ps が「対象プロジェクト 1 つのコンテナ状態」を表示するのに対し、 devbase list は「全プロジェクトの横断一覧」を表示します。

環境の全体像

# コンテナ、プラグイン、環境変数、スナップショットの状態を一括確認
devbase status

ベストプラクティス

  1. プロジェクト固有のファイルは /work に配置する -- /persistent/ai(~/.claude 等の symlink 先・~/share)は全コンテナで共有されるため
  2. scale は必要最小限に設定する -- リソース消費を抑制
  3. 作業終了後は devbase down を実行する -- 自動ローテーションでディスク容量を管理
  4. devbase ps で状態を確認してからログインする -- 異常終了したコンテナへのログイン試行を避ける
  5. イメージのビルドは初回と更新時のみ -- 変更がない場合はキャッシュが利用される