
AIエージェントを安全に動かすサンドボックス環境の作成
Claude Code の Auto Mode や GitHub Copilot CLI の Autopilot など、AIエージェントを自律的に動かす機能があります。
これらは非常に便利な反面、ホスト環境で直接動かすのは少し不安です。依存パッケージが汚染されたり、意図しないファイルを書き換えられたりするリスクがあります。
そこで今回は、エージェントをコンテナ内に閉じ込めつつ、ホストのプロジェクトディレクトリをシームレスに扱えるサンドボックス環境を作成しました。
https://github.com/yutakahashi114/sandbox
概要
このツールは1つのシェルスクリプト sandbox を実行するだけで、Docker コンテナ上の開発環境に入ることができます。
$ sandbox # 現在のディレクトリで新しいセッションを開く
$ sandbox -- <cmd> # コンテナ内で任意のコマンドを直接起動
$ sandbox --docker # Docker-in-Docker モードで起動
$ sandbox --browser 6080 # ブラウザ + VNC 付きで起動
コンテナは Ubuntu 24.04 ベースで、Claude Code や Codex CLI など、自分が使うものをインストールしています。
install.sh を編集して独自のツールを追加できます。
工夫したポイント
1. Git ディレクトリ構造を正しく扱う
単純に docker run -v $PWD:/workspace するだけでは、git worktree やサブモジュールを使っている場合に .git が参照できず、エージェントが git 操作に失敗してしまいます。
このツールは起動時に git の構成を自動判定して、最適なマウント戦略を選択します。
通常リポジトリ
└─ リポジトリルートをまるごとマウント(サブディレクトリ実行時も .git が見える)
Git Worktree
├─ 元リポジトリ → 読み取り専用でマウント
├─ worktree ディレクトリ → 書き込み可でマウント
└─ .git/worktrees/ → 書き込み可でマウント(ログ書き込みに必要)
サブモジュール
├─ 親リポジトリ → 読み取り専用でマウント
├─ サブモジュール作業ディレクトリ → 書き込み可でマウント
└─ .git/modules/<name> → 書き込み可でマウント
さらに settings/rw-dirs というファイルに書いたパスは、読み取り専用でマウントされたディレクトリ配下であっても書き込み可にオーバーライドできます。モノレポで一部のサブディレクトリだけ書き込みを許可したい場合などに活用できます。
2. エージェントの設定を自動同期する
コンテナ内でエージェントを使うには、ホスト側の認証情報や設定ファイルが必要になります。毎回手動でコピーするのは手間がかかるため、起動時に自動同期するようにしました。
ホストの ~/.claude/... や ~/.codex/... などから必要なファイルや設定をコピーしています。
3. コンテナを使い回す
同じディレクトリで sandbox を複数回呼んだとき、毎回新しいコンテナを起動するのは時間がかかります。そこで、起動時に docker ps で同じディレクトリのラベルを持つコンテナを探し、既存のコンテナに docker exec で入る設計にしました。
EXISTING=$(docker ps --filter "label=sandbox.host_pwd=${MOUNT_SOURCE}" -q | head -1)
if [[ -n "$EXISTING" ]]; then
docker exec ... "$EXISTING" zsh
fi
コンテナ自体はバックグラウンドで sleep infinity で待機しており、exec セッションが 0 になったら自動停止します。
4. ホームディレクトリのパス構造を保持する
ホスト側が ~/my-project だった場合、コンテナ内でも /home/developer/my-project としてマウントされます。絶対パスをベタ書きしたスクリプトが壊れることなく動作します。
5. ブラウザ操作に対応する
--browser PORT オプションを指定すると、コンテナ内で仮想ディスプレイ(Xvfb)+ Chromium + VNC サーバが起動し、noVNC 経由でブラウザの GUI 操作ができます。git worktree でフロントのちょっとした修正を確認するために使えます。
$ sandbox --browser 6080
# ブラウザで http://localhost:6080/vnc.html を開く
6. Docker-in-Docker に対応する
--docker オプションを指定すると --privileged で起動し、コンテナ内で Docker デーモンが立ち上がります。エージェントが docker コマンドを使うタスクを実行させる際に利用できます。
今回の主目的ではありませんが、git worktree で開発する際にアプリのポートが被らないので並行して起動できます。
ディレクトリ構成
sandbox/
├── sandbox # メインスクリプト(コンテナ起動・接続)
├── Dockerfile # Ubuntu 24.04 ベースイメージ定義
├── entrypoint.sh # コンテナ起動時の初期化処理
├── install.sh # ツール類のインストール(ビルド時に実行)
├── mount/ # ここに置いたファイル/ディレクトリを ~/.xxx にマウント
└── settings/ # 起動時に自動生成される設定ファイル群
├── ...
└── rw-dirs # 読み取り専用領域内で書き込みを許可するパス一覧
mount/ ディレクトリに置いたファイルやディレクトリは、ホームからの相対パスを保ったままコンテナにマウントされます。たとえば mount/.npmrc を置けばコンテナ内の /home/developer/.npmrc になります。
使い方
セットアップ
git clone git@github.com:yutakahashi114/sandbox.git ~/<dir>
echo 'export PATH="$HOME/<dir>:$PATH"' >> ~/.zshrc
source ~/.zshrc
初回起動時にイメージが自動ビルドされます(数分かかります)。
install.sh を編集して独自のツールを追加できます。
基本的な使い方
cd ~/my-project
sandbox # コンテナ内の zsh に入る
sandbox -- claude # Claude Code を起動
sandbox -- codex # Codex CLI を起動
まとめ
AIエージェントを閉じ込めつつ、設定や作業ディレクトリはシームレスに渡すような Docker サンドボックスを作成しました。
特に git worktree やサブモジュールを多用する環境でも正しく動くよう、マウント戦略を細かく調整しました。
安全性を重視して Git の認証情報等は渡していませんが、やろうと思えばできると思います。
また、コンテナからのネットワーク接続は制限しておらず、エージェントが外部への通信を行う可能性があります。
100%安全とは言えませんが、ホストで直接実行するよりは安心感があって良いです。