Docker Sandboxes

応用 — 構成の再利用と発展運用

サンドボックスの中身をコード化する Kit、イメージの焼き込み、環境変数や AWS 資格情報の渡し方、 clone の成果物の回収法、放置気味の自律運用までをまとめる。日常の起動とワークスペース選択は 使い方を先に読む。

Kitテンプレート自律運用

検証: sbx v0.35.0・macOS (Apple Silicon)

1.Kit — サンドボックス構成をコード化する


Kit は、1 つのサンドボックスの中身を YAML で宣言する仕組みである( sbx kit --help)。 使うテンプレートや起動コマンド、許可する通信先、環境変数、エージェントへ配る設定ファイルなどをまとめて書いておき、sbx run … --kit <ディレクトリ> でその構成のサンドボックスを作れる。 一方、ホスト側のどのパスをマウントするか(rw / ro)は spec.yaml ではなく、作成時のパス引数で指定する (sbx v0.35.0 で確認。sbx kit validate もマウント用フィールドを受け付けない)。 列挙が要るのは初回作成のときだけで、2 回目以降は名前で再アタッチすれば保存済みのマウント構成が使われる (通常の run と同じ。使い方のワークスペース節)。 --kit も作成時にだけ効く。プロジェクトのリポジトリに入れておけば同じ環境を再現でき、 sbx kit pack / push / pull で OCI レジストリ経由の配布もできる。

既知のツールにたとえると、対象は Docker Compose とは違う。 Compose は複数コンテナのオーケストレーションを定義するのに対し、 Kit はサンドボックス 1 個の中身を宣言する。 1 環境の設定をコードに落とす感覚は devcontainer.json に近い 。

以下は使い方:エージェント別と同じ 4 例 (Claude Code / OpenAI Codex / cursor-agent / Grok Build)を Kit 化する。 前三者は公式テンプレートを sandbox.image に書くだけ。 Grok Build だけは公式未対応のため、イメージを自作してから Kit で包む。

完成済みイメージを指定するだけならホスト側 Docker は不要

Claude Code / OpenAI Codex / cursor-agent のように、レジストリ上の既存テンプレートを sandbox.image に書くだけの Kit には、Docker Desktop は不要。 ホストで docker build する手順(Grok Build のタブや 独自テンプレート)だけが例外である。

sbx/kits/claude-code/spec.yaml
schemaVersion: "1"
kind: sandbox
name: claude-code
sandbox:
  image: "docker/sandbox-templates:claude-code-docker"
  aiFilename: CLAUDE.md
  entrypoint:
    run: [claude, "--dangerously-skip-permissions"]  # 公式デフォルトと同じ YOLO。外すなら [claude] のみ
network:
  allowedDomains:
    - api.anthropic.com:443
    - github.com:443
Kit を指定して作成(マウント列挙は初回だけ)
# ―― 初回: --kit とマウントを列挙して作成(構成はサンドボックスに保存される)――
# 第1パス = プライマリ(rw)。第2パス以降は追加マウント(ro → path:ro)。マウントは spec.yaml には書けない
$ sbx run claude-code --kit ./sbx/kits/claude-code . ~/shared-libs:ro
$ sbx run claude-code --kit ./sbx/kits/claude-code ~/proj ~/docs:ro ~/design:ro

# ―― 2回目以降: マウントも --kit も不要。名前で再アタッチ ――
$ sbx run --name claude-code
$ sbx exec -it claude-code bash
sbx/kits/openai-codex/spec.yaml
schemaVersion: "1"
kind: sandbox
name: openai-codex
sandbox:
  image: "docker/sandbox-templates:codex-docker"
  aiFilename: AGENTS.md
  entrypoint:
    run: [codex, "--dangerously-bypass-approvals-and-sandbox"]  # 公式デフォルトと同じ YOLO。外すなら [codex] のみ
network:
  allowedDomains:
    - api.openai.com:443
    - openai.com:443
    - auth.openai.com:443
    - github.com:443
Kit を指定して作成(マウント列挙は初回だけ)
# ―― 初回 ――
$ sbx run openai-codex --kit ./sbx/kits/openai-codex . ~/shared-libs:ro
$ sbx run openai-codex --kit ./sbx/kits/openai-codex ~/proj ~/docs:ro

# ―― 2回目以降 ――
$ sbx run --name openai-codex
$ sbx exec -it openai-codex bash
sbx/kits/cursor-agent/spec.yaml
schemaVersion: "1"
kind: sandbox
name: cursor-agent
sandbox:
  image: "docker/sandbox-templates:cursor-agent-docker"
  aiFilename: AGENTS.md
  entrypoint:
    run: [cursor-agent, "--yolo"]  # 公式デフォルトと同じ YOLO。外すなら [cursor-agent] のみ
network:
  allowedDomains:
    - api2.cursor.sh:443
    - api3.cursor.sh:443
    - github.com:443
Kit を指定して作成(マウント列挙は初回だけ)
# ―― 初回 ――
$ sbx run cursor-agent --kit ./sbx/kits/cursor-agent . ~/shared-libs:ro
$ sbx run cursor-agent --kit ./sbx/kits/cursor-agent ~/proj ~/docs:ro

# ―― 2回目以降 ――
$ sbx run --name cursor-agent
$ sbx exec -it cursor-agent bash

エージェント別の使い方で手作業でやった Grok Build のセットアップ (shell テンプレートのサンドボックスに入って install.sh …)を Kit 化しておくと、消してもワンコマンドで再現できる。 ベースは docker/sandbox-templates:shell-dockersbx template ls で確認)。

⚠️ このタブの Dockerfile ビルドだけはホスト側 Docker が必要

以下はホストのシェルで docker build / docker image save を実行する。 macOS では Docker Desktop など、ホスト側でイメージをビルドできる環境を別途用意する。

sbx/kits/grok-build/Dockerfile
FROM docker/sandbox-templates:shell-docker

# grok CLI を焼き込む(インストール先の PATH 設定は install.sh が ~/.bashrc に書く)
RUN curl -fsSL https://x.ai/cli/install.sh | bash
ビルドしてテンプレート登録
$ docker build -t myname/grok-build ./sbx/kits/grok-build && \
  sbx template load <(docker image save myname/grok-build)
sbx/kits/grok-build/spec.yaml
schemaVersion: "1"
kind: sandbox
name: grok-build
sandbox:
  image: "myname/grok-build"
  entrypoint:
    run: [grok]          # shell ではなく grok を直接起動
network:
  allowedDomains:
    # ホスト名は完全一致。x.ai だけでは api.x.ai 等は通らない
    - x.ai:443           # 頂点ドメイン自体
    - "*.x.ai:443"       # サブドメイン一括(sbx policy allow network と同系。ワイルドカード可)
    # 実際に必要なホストは sbx policy log で確認して足す
作成(マウント列挙は初回だけ)
# ―― 初回: Kit とマウントをここで固定 ――
$ sbx run grok-build --kit ./sbx/kits/grok-build --name grok-build . ~/shared-libs:ro
$ sbx run grok-build --kit ./sbx/kits/grok-build --name grok-build ~/proj ~/docs:ro

# ―― 2回目以降: 名前だけで再アタッチ(マウントも --kit も付け直さない)――
$ sbx run --name grok-build
$ sbx exec -it grok-build bash

ツールは焼き込めるが、OAuth 認証だけはサンドボックスを作り直すたびに初回 1 回必要。

各タブの --kit に渡しているパス( ./sbx/kits/claude-code./sbx/kits/openai-codex./sbx/kits/cursor-agent./sbx/kits/grok-build)は、 ホスト側にある Kit 用ディレクトリを指す。 ディレクトリ名は自由に決めてよい (中身の spec.yaml--kit の指し先が一致していればよい)。 置き場所の例は次のとおり。

  • プロジェクト配下に my-kit/ ディレクトリを作り、その中に spec.yaml を置く → --kit ./my-kit
  • プロジェクトのルートに直接 spec.yaml を置く → --kit .

必要なのは、--kit が指すディレクトリに spec.yaml があることである。 同じディレクトリに files/home/ を作ってファイルを置くと、起動時に サンドボックス(VM)内の HOMEへ配布される (例: ホストの …/files/home/.claude/settings.json → サンドボックス内の ~/.claude/settings.json)。 files/home/ というパス自体は VM 内には存在しない。ホストの Kit ディレクトリ側に自分で用意する配布用の置き場で、中身が HOME に撒かれるだけである。

共有の GitHub 上 Kit をそのまま足す例: sbx run --kit "git+https://github.com/docker/sbx-kits-contrib#subdir" claude . (こちらは既存エージェントに mixin する形。上の 4 タブは sandbox キットでエージェントごと定義する例)。

spec.yaml のフィールドや詳しい書き方は、 公式の Kits 解説Kit spec reference を参照。 チーム向けにオプション依存だけを足す kind: mixin もあるが、個人利用ではほぼ不要 (詳細は Qiita の解説 を参照)。

2.VM イメージ自体のカスタマイズ


⚠️ ホスト側 Docker が必要

ここでのビルドはホストのシェルで docker build / docker image save を実行する。 通常の sbx run や、完成済みテンプレートの利用には不要。

ビルドツールや CLI を焼き込みたければ、公式テンプレートを FROM した Dockerfile を作ってロードする。

⚠️ Dockerfile の ENV だけでは足りないことがある

イメージに焼き込んだ環境変数の一部は、サンドボックス起動時の初期化で上書きされうる (PS1 やツールの activate など)。 シェル初期化として残したい設定は /etc/sandbox-persistent.sh に追記するのが定石。 起動時だけ差し込むなら sbx exec -e環境変数節)で足りる場合もある。

Dockerfile
FROM docker/sandbox-templates:claude-code-docker

RUN claude update
RUN sudo apt update -y && sudo apt install -y build-essential
# 永続させたいシェル初期化はここへ(ENV だけに頼らない)
RUN echo 'eval "$(mise activate bash)"' >> /etc/sandbox-persistent.sh
ビルドしてテンプレートとして登録
$ docker build -t myname/claude-code ./sbx/kits/claude-code && \
  sbx template load <(docker image save myname/claude-code)
$ sbx template ls

ローカルで template load したイメージは sbx template lsdocker.io/… のように見えることがあるが、レジストリへ push したわけではない。 ベーステンプレートの Dockerfile は非公開でも、ホストに Docker があれば docker history で層の概要を覗ける場合がある。

3.環境変数と AWS 認証情報


ここでは既に動いているサンドボックスへ、ホストから一時的に環境変数を足す方法を扱う。 Kit の environment.variables や Dockerfile の ENV は作成・イメージ側の話で、 起動のたび/コマンドごとに変えたい値には向かない。そういうときが sbx exec -e である。

実行時に環境変数を渡す

sbx exec-e NAME=value(またはホストに既にある -e NAME)で、その一回のコマンドにだけ変数を渡せる。 サンドボックスの永続状態には残らない。デバッグ用のフラグや、作業ディレクトリ固有の設定を その場で足す用途に向く。

実行時に環境変数を渡す
$ sbx exec -it -e FOO=bar mybox bash   # この bash セッションにだけ FOO が付く

AWS 認証情報の特例的な渡し方

エージェントに AWS CLI や SDK を触らせたい場面がある。多くの SaaS 向け API キーは 安全性で述べるサービス資格情報のプロキシ注入で渡せ、 生の秘密を VM に入れずに済む。

ところが AWS の署名(SigV4)はプロキシがヘッダを差し替える方式では扱えない。 そのため AWS だけは、ホスト側で用意したアクセスキー等を環境変数として VM に渡す運用になりやすい。 渡した値はサンドボックス内から読めるので、長命なキーを直書きするのは避け、 aws-vault などで短命クレデンシャルを出してから sbx exec -e で渡すのが定石である。

aws-vault で短命クレデンシャルを渡す
# ホスト: aws-vault が一時キーを環境に載せたうえで sbx exec を起動する
# -e NAME だけ書くと「ホストの同名変数をそのまま渡す」
$ aws-vault exec dev -- sbx exec -it \
  -e AWS_REGION -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \
  -w $(pwd) $(basename $(pwd)) bash

上の例は、カレントの作業ツリーをワークスペース名にした既存サンドボックスへ入り、 AWS 用の 4 変数だけをそのセッションに載せている。 権限は aws-vault プロファイル側で最小に絞る。詳細は安全性を参照。

4.成果物の回収


clone モードでサンドボックス内でファイルを追加・変更した後、ホスト側へ成果物を回収する方法としては、次の3通りが考えられる。

ファイル単位でコピー

変更が数ファイルなら sbx cp でホストへ取り出す。

clone モード専用: ホストの Git 作業ツリーへ fetch

--clone で作ると、ホスト側リポジトリに sandbox-<サンドボックス名> という Git remote が付く (例: 名前が fix-issue-123 なら remote 名は sandbox-fix-issue-123sbx create --help の説明どおり)。 エージェントが VM 内クローンへ積んだコミットを、ホストの作業ツリーから git fetch で取り込める。外部ホスティングへの push は不要。

外部ホスティングへ push → PR/MR

サンドボックス内でブランチを切りコミットしたあと、GitHub 等へ git push し、 ホスト側ブラウザで Pull / Merge Request を開く。

はレビュー機能付きのリモートがあることが前提

Git 本体には Pull Request / Merge Request の仕組みはない。これらを使って成果物を回収するというのは、 GitHub、GitLab、Bitbucket、Gitea など、レビュー用の PR/MR 機能を持つホスティング (クラウドでも社内設置でもよい)にリモートがある場合の話である。 bare な Git リポジトリを置いているだけでは、この方式の PR/MR は使えない。

成果物の回収例
# A: ファイル単位
$ sbx cp fix-issue-123:/Users/me/project/some-file .

# B: clone モード — ホストのリポジトリで、sandbox 用 remote から取り込む
$ cd ~/path/to/repo                    # --clone を起動したホスト側リポジトリ
$ git remote -v                        # sandbox-fix-issue-123 などが付いているか確認
$ git fetch sandbox-fix-issue-123      # VM 内クローンのコミットを取得
$ git log --oneline sandbox-fix-issue-123/<branch>
$ git merge sandbox-fix-issue-123/<branch>   # または cherry-pick / 別ブランチへ checkout

が使えない(ホスティングが無い、または外へ push したくない)ときは でローカルに回収する。 --clone で作ったサンドボックス向け。通常マウント(rw)ならホストに直接書き込んでいるので不要。 clone の起動例自体は使い方:ワークスペースを参照。

5.自律エージェント運用パターン


Zenn の記事が示すように、 Docker Sandboxes が一番効くのは「サンドボックス上で Issue を読み、バグ修正を行い、プルリクエストを作ってもらう」 ような自律運用。--clone でホストの作業ツリーに触れさせず、成果は 上記の回収法に寄せると、 YOLO モードで放置する場合もホスト側の被害半径を縮小できる。 ただし、許可済みドメインと付与した資格情報の権限内では外部操作が可能。