セルフホスト Dev Sandbox:Docker と Go でプレビュー環境を作る
"sandboxed README は Go 制御プレーン、Docker、Traefik、SQLite、preview URL、idle stop、本番前の hardening 境界を説明しています。"
"Docker の resource constraints 文書は、コンテナにはデフォルトで CPU とメモリの制限がなく、明示的な制約が必要だと説明しています。"
"Docker Sandboxes 文書は、microVM、独立 Docker daemon、ネットワーク proxy、credential isolation をより強いセキュリティモデルとして説明しています。"
"Traefik Docker provider は Docker labels からルーティング設定を取得し、Host rule でコンテナサービスへ転送できます。"
Preview URL は小さな機能に見えます。コンテナ内で 3000 番ポートを起動し、ユーザーにリンクを渡せば終わり。実際に作ると、セルフホスト Dev Sandbox はポート衝突、ドメインルーティング、コンテナ回収、ファイル永続化、API からの制御をまとめて引き出します。AI コーディング製品では特に早くこの問題に当たります。Agent がコードを書いたあと、ユーザーが見たいのはログではなく、クリックできる結果です。
ここでは docker run を 1 行書くだけでは足りません。安定させるには 4 つに分けます。1 台の Linux ホスト、コンテナ管理の Docker、ライフサイクル管理の Go 制御プレーン、プレビュー用ドメインの Traefik、状態保存の SQLite。信頼できるチームや初期プロダクト検証には向いています。一方で、不特定ユーザーの任意コードを動かすなら、コンテナ方式は最初の 1 層にすぎません。microVM、専用ホスト、Kubernetes まで視野に入れる必要があります。
短命な環境が多いときに使う。個人の 2 コンテナには重い
個人プロジェクトなら、2 個のコンテナ、2 個のポート、docker compose up -d で十分なことがほとんどです。Dev Sandbox に価値が出るのは、環境数が増え、ライフサイクルが短くなり、外部システムから各環境を作成する必要が出たときです。
| シーン | セルフホスト Dev Sandbox は合うか | 理由 |
|---|---|---|
| 個人の長期 demo を 1 つ動かす | あまり不要 | shell script や Compose のほうが簡単 |
| チームで branch ごとにプレビュー環境を作る | 向いている | 自動作成、ルーティング、回収、状態記録が必要 |
| AI app builder がユーザー向けに小さなアプリを生成する | とても向いている | Agent が隔離ディレクトリでコードを書き、preview URL をすぐ返す必要がある |
| 公開サービスで不特定ユーザーの任意コードを動かす | prototype まで | Docker コンテナは強い隔離境界ではなく、本番では VM / microVM が必要 |
| 複数ノード、大規模スケジューリング、複雑なネットワークポリシー | 単一ホストでは不足 | Kubernetes や managed platform のほうが安定する |
多くの開発者は最初に、Agent に shell script を書かせればよいのでは、と考えます。これは自然な疑問です。script は「コンテナを 1 つ起動する」問題を解けます。ただし、「50 個の環境を同時に維持する」「idle になったら停止する」「次のアクセスで自動復帰する」「ファイルを残す」「各環境に安定した URL を渡す」「SaaS backend から API で呼べるようにする」までは扱いにくい。要件が積み上がると、script は制御プレーンに近づいていきます。
最小構成:Go 制御プレーン、Docker、Traefik、SQLite
tastyeffectco/sandboxes の設計はかなり小さく保たれています。Go プログラムの sandboxd が Docker コマンドを発行し、Traefik がコンテナ labels から動的ルーティングを行い、SQLite が状態を保存し、workspace はディスク上に置かれます。Kubernetes も、独立 database server も、message queue もありません。
browser
|
v
Traefik ----> sandbox container ----> dev server :3000
^ ^
| |
sandboxd --------------+
|
+-- SQLite: sandbox 状態、ポート、タスク
+-- workspaces/: sandbox ごとの永続ディレクトリ
+-- reaper: idle stop / memory pressure stop
この構成では 4 つの対象を分けて考えます。
制御プレーンは業務コンテナではない
Go 制御プレーンが担うのはライフサイクルです。sandbox の作成、停止、削除、コマンド実行、Agent task の投入、ファイル読み書き。薄く保つほうが扱いやすいです。ビルドロジックを全部ここに押し込まず、複雑な処理は sandbox ベースイメージ、タスクキュー、上位アプリへ逃がします。
Preview URL はランダムポートではない
各 sandbox は s-<id>-3000.preview.localhost のようなアドレスを公開できます。Traefik は Docker labels から対象コンテナと対象ポートを見つけ、Host rule でリクエストを転送します。ユーザーに見せるのは安定したリンクです。「あなたのポートは 30017 です。衝突しないように気をつけてください」ではありません。
SQLite は小さなシステムの状態アンカー
コンテナは再起動します。ホストも再起動します。Traefik も reload されることがあります。SQLite は sandbox ID、ポート、状態、タスク、workspace 位置を記録します。制御プレーンの起動後、Docker の実状態と database を reconcile できます。単一ホストの初期プロダクトなら SQLite で十分です。ただし、その境界を受け入れ、バックアップすることが前提です。
ローカルで動かす:まず API、ポート、ドメイン解決を確認する
Agent 連携を急がないほうがよいです。まず、制御プレーンがコンテナを起動できるか、Traefik が転送できるか、preview URL が開くかを確認します。sandboxes README の quick start はかなり直接的です。
git clone https://github.com/tastyeffectco/sandboxes.git
cd sandboxes
./install.sh
API=http://127.0.0.1:9090
curl "$API/healthz"
health check が通ったら、3000 番ポートで配信する sandbox を作ります。
ID=$(curl -s -XPOST "$API/sandbox" \
-H 'content-type: application/json' \
-d '{"ports":[3000]}' | sed -E 's/.*"id":"([^"]+)".*/\1/')
curl -s -XPOST "$API/sandbox/$ID/exec" \
-H 'content-type: application/json' \
-d '{"cmd":["bash","-lc","cd ~/workspace && python3 -m http.server 3000"]}'
その後、次の URL を開きます。
http://s-<id>-3000.preview.localhost
*.localhost は現代的なブラウザではローカルマシンへ解決されるため、DNS なしのローカル検証に便利です。実ドメインへ移す場合は、*.preview.yourdomain.com をホストへ向け、Traefik で TLS を処理します。127.0.0.1:9090 のようなローカル API をそのまま公開しないでください。本番では少なくとも token 認証を有効にし、制御プレーンのポートは firewall や private gateway の内側に置きます。
Preview URL の難所は routing、wake、persistence
普通のポート転送が扱うのは「コンテナが起動しているときにどうアクセスするか」です。Dev Sandbox はさらに、「コンテナが眠っているときはどうするか」「ファイルはどこに置くか」「同じユーザーが戻ってきたときに続けられるか」を扱います。この 3 つが demo から内測へ進めるかを決めます。
ルーティング:ドメインを環境 ID として使う
ポート番号はマシン側の視点です。ドメインはプロダクト側の視点です。s-<id>-3000.preview.example.com には sandbox ID と対象ポートが含まれるため、上位アプリはそのリンクをそのままユーザーへ表示できます。Traefik の Docker provider はコンテナ labels を読み、Host rule に基づいて該当コンテナへ送ります。
排障はこの順番で見ます。
- DNS:wildcard ドメインがホストへ向いているか。ローカルでは
*.localhostを使っているか。 - Traefik:コンテナに正しい labels が付いているか。同じ Docker network にいるか。
- ポート:アプリが
0.0.0.0:3000で listen しているか。127.0.0.1だけではないか。 - readiness:アプリ起動直後の待機ページや retry 戦略があるか。
- TLS:実ドメインで wildcard 証明書が設定され、HTTP と HTTPS の entrypoint が揃っているか。
Wake:idle stop は環境削除ではない
idle になった sandbox は docker stop できます。これでメモリを解放しつつ、workspace ディレクトリはディスクに残せます。次にユーザーが preview URL を開くと、低優先度の catch-all route がリクエストを制御プレーンへ渡します。制御プレーンはコンテナを起動し、ポートが ready になるのを待ち、ブラウザを実アプリへ入れます。
この仕組みは、すべてを常時起動するより省リソースです。静かになった瞬間に環境を消すよりも、プロダクトらしい体験になります。代償は cold start です。ユーザーに 502 を見せるのではなく、warming 状態を出すほうがよいです。
永続化:bind mount は便利だが境界を理解する
Docker 公式文書でも、bind mount はソースコードや build artifact の共有でよく使われます。Dev Sandbox でも同じです。sandbox ごとに 1 つの host ディレクトリを用意し、コンテナの workspace へ mount します。メリットは、コンテナを消してもコードが残ること。デメリットは、host path と権限がシステム設計の一部になることです。
内測前に最低 3 つ決めておきます。workspace ディレクトリを制御プレーンの設定と混ぜないこと。sandbox の削除と workspace の削除を別操作にすること。バックアップ対象は workspace と SQLite であり、コンテナ layer から重要状態を救う設計にしないこと。
マルチテナントの最低ライン:リソース制限、Docker socket、API auth、イメージキャッシュ
Docker の resource constraints 文書ははっきりしています。コンテナにはデフォルトでリソース制約がなく、ホスト kernel scheduler が許す範囲で CPU とメモリを使えます。マルチテナント環境では危険です。1 人の npm install、ビルド、無限ループがホスト全体を遅くする可能性があります。
まずはこのチェックリストから始めます。
- 各 sandbox にメモリ、CPU、PIDs 制限を設定する。
- 制御プレーン API はデフォルトで localhost または private network のみに置き、公開入口には認証を必須にする。
- preview link は基本的に共有可能リンクとして扱う。機密情報があるなら forward-auth を入れる。
- ベースイメージに共通ツールを入れ、sandbox ごとの再 pull を減らす。
- Docker Hub には公式の rate limit と fair use ルールがある。本番ではログイン、イメージキャッシュ、private registry を用意する。
- sandbox workspace を分離して mount し、ユーザーコンテナへ
/var/run/docker.sockを渡さない。 - 作成、停止、削除、コマンド実行、Agent task の監査ログを残す。
Compose のリソース制限例は次のようになります。
services:
sandbox-app:
image: your-sandbox-base:latest
deploy:
resources:
limits:
cpus: "1.00"
memory: 1G
pids: 256
より大きな注意点は Docker socket です。sandboxd が host Docker socket を mount している場合、それはホストに対して強い権限を持ちます。この設計は、「制御プレーンは自分たちが管理し、ユーザーは作成された sandbox コンテナだけに入る」前提なら受け入れられます。ユーザーが制御プレーンコンテナへ影響できる、または Docker socket を取れるなら、リスクは普通のコンテナ隔離を越えます。
microVM、Kubernetes、managed platform へ移るタイミング
単一ホスト Docker の利点は、安い、読みやすい、変えやすいことです。弱点も明確です。容量は 1 台分に限られ、セキュリティ境界はコンテナ隔離とホスト運用に大きく依存し、スケジューリング能力は cluster より弱くなります。
| きっかけ | より合う方向 |
|---|---|
| 不特定ユーザーの任意コードを実行する | microVM、専用 VM、gVisor、Kata、Firecracker |
| Agent に完全な Docker 能力を渡したいが host daemon には触らせたくない | Docker Sandboxes のような microVM + 独立 daemon |
| 複数ホストのスケジューリング、弾力的な拡縮、統一ネットワークポリシー | Kubernetes |
| チームが低レイヤーの制御面を保守したくない | managed preview-environment platform |
| まだプロダクト需要を検証している | 単一ホスト Docker + Go 制御プレーン |
Docker 公式 Sandboxes の security model はよい参照になります。AI agent を microVM に入れ、各 sandbox に独自の Docker daemon、filesystem、network を持たせ、host Docker daemon を sandbox から切り離します。リソース消費は増えますが、隔離境界は明確です。
最初は単一ホストでプロダクトの loop を確認すれば十分です。環境を作る。Agent にコードを書かせる。プレビューを開く。idle な sandbox を回収する。ファイルを残す。実ユーザーが入ってから、実際のリスクに応じて隔離層を上げます。まだ存在しない規模問題のために、最初から cluster 運用へチームを引きずり込む必要はありません。
MVP から内測までの実践チェックリスト
一度に全部作る必要はありません。次の順番で進められます。
- sandbox 関連サービスだけを動かすきれいな Linux ホストを選ぶ。database、CI runner、本番アプリと同居させない。
*.preview.example.comのような wildcard preview domain を設定する。ローカルでは先に*.localhostで検証する。- 制御プレーン API を確認する:create、exec、stop、destroy、healthz。
- sandbox ベースイメージに Node.js、Python、Git、よく使う package manager、対応する Agent CLI を入れる。
- 各 sandbox にリソース制限、idle 回収、workspace 永続化、削除ポリシーを設定する。
- API auth を有効にし、必要に応じて preview link にアクセス制御を入れる。
- 監査ログを記録する。ホストメモリ、ディスク、コンテナ数、cold start time、502 比率を監視する。
- SQLite、workspace ディレクトリ、
.env、ベースイメージのビルドスクリプトについて backup / restore 演習を行う。
次の段階でコードプレビューを CI へつなぐなら、GitHub Actions セルフホスト Runner:プライベート環境デプロイ完全ガイド が参考になります。生成された Next.js アプリを長期運用するなら、Vercel から離れる:Next.js Docker セルフホスト完全ガイド が後半の話に近いです。公開ドメインと origin protection は、Cloudflare origin IP allowlist 設定 へ進めます。
よくある質問
Dev Sandbox と普通の Docker Compose は何が違いますか?
Compose は「サービス群を宣言し、起動する」ものに近いです。Dev Sandbox は「プロダクト backend が要求に応じて環境を作成、停止、復帰、削除し、それぞれに URL を渡す」仕組みです。環境数が少なく、寿命が長いなら Compose で十分です。ユーザー、branch、Agent task ごとに動的作成するなら制御プレーンが必要です。
なぜ Kubernetes を使わないのですか?
すでに cluster、Ingress、イメージレジストリ、権限、監視があるなら、Kubernetes は標準化された環境基盤として強力です。ただし、多くの初期チームは AI app builder や社内プレビュー環境を検証したいだけで、cluster 運用のほうがプロダクトより重くなりがちです。単一ホスト Docker は Kubernetes の代替ではなく、最初の段階を軽くする選択です。
コンテナ隔離で不特定ユーザーのコードを実行できますか?
そのまま実行するのはおすすめしません。コンテナは信頼できるチーム、社内ユーザー、低リスク demo に向いています。不特定ユーザーの任意コードは、microVM、専用 VM、gVisor、Kata、Firecracker、または少なくとも tenant ごとに分けたホストで動かすべきです。
Preview URL は必ず HTTPS が必要ですか?
ローカルの *.localhost なら HTTP から始められます。公開ドメインでは HTTPS を使うのが無難です。特に token、フォーム、業務データを入力する場合は必須に近いです。wildcard 証明書を使うと、sandbox ごとに個別証明書を発行する手間を減らせます。
idle stop 後にファイルは消えますか?
workspace が永続ディレクトリなら、docker stop でファイルは消えません。本当に注意すべきなのは destroy と purge の違いです。片方はコンテナだけを消し、もう片方は workspace も消します。プロダクト UI と API 名でこの違いを明確にしてください。
Docker Hub の rate limit は影響しますか?
影響します。多くの環境が頻繁に起動、ビルド、イメージ pull を行うと、公開 registry が不安定要因になります。本番では Docker Hub にログインし、private registry やイメージキャッシュを用意し、よく使う依存関係をベースイメージへ入れておくのが安全です。
まとめ
セルフホスト Dev Sandbox は作る価値があります。ただし、高機能な docker run ではありません。小さなプラットフォームです。制御プレーンがライフサイクルを扱い、reverse proxy が URL を扱い、状態ストアが復旧を支え、リソース制限とセキュリティポリシーが 1 つの環境にホスト全体を引きずられないようにします。
安定した進め方は、まず単一ホスト Docker でプロダクトの loop を作り、実際のリスクに応じて強化することです。ユーザーが少なく、コードを信頼でき、チームが単一ホスト境界を受け入れられるなら、Go + Docker + Traefik + SQLite で十分です。不特定ユーザー、強い隔離、複数ホスト、コンプライアンスガバナンスが出てきたら、microVM、Kubernetes、managed platform を検討する段階です。
参考資料
- tastyeffectco/sandboxes
- Docker Resource constraints
- Docker Engine security
- Docker Hub usage and limits
- Docker Sandboxes security model
- Traefik Docker provider
セルフホスト Dev Sandbox MVP の作り方
単一ホストの Docker 検証から内測前の安全チェックまでの実践手順。
⏱️ 目安時間: 4 時間
- 1
ステップ1: 専用ホストを用意する
sandbox 関連サービスだけを動かす Linux ホストを用意します。本番データベース、CI runner、重要な業務サービスと同居させないでください。 - 2
ステップ2: プレビュー用ドメインを設定する
まず `*.localhost` でローカル検証します。実環境では `*.preview.example.com` をホストへ向け、TLS を設定します。 - 3
ステップ3: 制御プレーン API を検証する
少なくとも create、exec、stop、destroy、healthz を確認し、上位アプリから API 経由で環境を管理できるようにします。 - 4
ステップ4: sandbox ベースイメージを準備する
Node.js、Python、Git、よく使うパッケージマネージャー、対応する Agent CLI を事前に入れておきます。sandbox 起動後の繰り返しセットアップを減らせます。 - 5
ステップ5: リソース制限と回収を入れる
各 sandbox に CPU、メモリ、PID 制限を設定し、idle stop、wake-on-request、永続 workspace を用意します。 - 6
ステップ6: 制御面とプレビュー入口を閉じる
API token、プライベートネットワーク、ファイアウォールルールを有効にします。機密性のある preview には forward-auth またはサービス側ログインを挟みます。 - 7
ステップ7: ログと監視を追加する
作成、停止、削除、コマンド実行、Agent task を記録します。ホストメモリ、ディスク、コンテナ数、冷間起動時間、502 比率を監視します。 - 8
ステップ8: バックアップと復旧を試す
SQLite、workspace ディレクトリ、`.env`、ベースイメージのビルドスクリプトをバックアップし、新しいホストで復旧できるか確認します。
FAQ
Dev Sandbox と普通の Docker Compose は何が違いますか?
なぜ Kubernetes を使わないのですか?
Docker コンテナ隔離で不特定ユーザーのコードをそのまま実行できますか?
Preview URL は必ず HTTPS にするべきですか?
idle stop 後にファイルは消えますか?
Docker Hub の rate limit は Dev Sandbox に影響しますか?
6分で読めます · 公開日: 2026年6月5日 · 更新日: 2026年6月8日
関連記事
Cloudflare Pro か Business か?3 つの軸で判断するアップグレード判断ツリー
Cloudflare Pro か Business か?3 つの軸で判断するアップグレード判断ツリー
社内ネットワーク Docker pull タイムアウトのトラブルシューティング:DNS・プロキシ・ミラー加速の完全ガイド
社内ネットワーク Docker pull タイムアウトのトラブルシューティング:DNS・プロキシ・ミラー加速の完全ガイド
Docker ミラーソース速度テスト実践:3 つの方法 + 自動切り替えスクリプト
コメント
GitHubアカウントでログインしてコメントできます