cloudflare-sandbox について
cloudflare-sandbox は、Workers で Cloudflare Sandboxes SDK を使うためのスキルガイドです。コンテナ実行、セッション、ファイル操作に加え、コンテナの一時性とデータの永続化方法を説明します。
主な機能
- 01コンテナ内でのコマンド実行
- 02シェルセッションと作業ディレクトリの管理
- 03ファイル操作と Git リポジトリのチェックアウト
- 04コードコンテキストとバックグラウンドプロセスの実行
- 05コンテナのライフサイクルとデータ永続化の扱い
活用シーン
- 01コーディングエージェント向けの一時実行環境
- 02同一セッションでの複数コマンド実行
- 03ビルド、テスト、データ処理の実行
- 04コールドスタートと外部ストレージへのバックアップ対応
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill cloudflare-sandboxインストール後、Claude Code で/cloudflare-sandboxを入力して読み込まれたか確認します。
同梱ファイルREADME.mdSKILL.json
詳細
Cloudflare Sandboxes SDK
ステータス:本番環境対応(オープンベータ)
最終更新日:2025-10-29
依存関係:cloudflare-worker-base、cloudflare-durable-objects(理解を深めるために推奨)
最新バージョン:@cloudflare/[email protected]、Docker イメージ:cloudflare/sandbox:0.4.12
クイックスタート(15 分)
1. SDK をインストールして Wrangler をセットアップする
npm install @cloudflare/sandbox@latest
wrangler.jsonc:
{
"name": "my-sandbox-worker",
"main": "src/index.ts",
"compatibility_flags": ["nodejs_compat"],
"containers": [{
"class_name": "Sandbox",
"image": "cloudflare/sandbox:0.4.12",
"instance_type": "lite"
}],
"durable_objects": {
"bindings": [{
"class_name": "Sandbox",
"name": "Sandbox"
}]
},
"migrations": [{
"tag": "v1",
"new_sqlite_classes": ["Sandbox"]
}]
}
これが重要な理由:
nodejs_compatは、SDK が必要とする Node.js API を有効にしますcontainersは Ubuntu コンテナイメージを定義しますdurable_objectsバインディングは永続的なルーティングを有効にしますmigrationsは Sandbox クラスを登録します
2. 最初の Sandbox Worker を作成する
import { getSandbox, type Sandbox } from '@cloudflare/sandbox';
export { Sandbox } from '@cloudflare/sandbox';
type Env = {
Sandbox: DurableObjectNamespace<Sandbox>;
};
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Get sandbox instance (creates if doesn't exist)
const sandbox = getSandbox(env.Sandbox, 'my-first-sandbox');
// Execute Python code
const result = await sandbox.exec('python3 -c "print(2 + 2)"');
return Response.json({
output: result.stdout,
success: result.success,
exitCode: result.exitCode
});
}
};
重要:
- Worker から
@cloudflare/sandboxの{ Sandbox }を必ずエクスポートしてください - Sandbox ID によってルーティング先が決まります(同じ ID = 同じコンテナ)
- 最初のリクエストでコンテナが作成されます(コールドスタートに約 2~3 分)
- 2 回目以降のリクエストは高速です(1 秒未満)
3. デプロイしてテストする
npm run deploy
curl https://your-worker.workers.dev
出力例:
{
"output": "4\n",
"success": true,
"exitCode": 0
}
アーキテクチャ(3 層モデルを理解する)
Sandboxes の仕組み
┌─────────────────────────────────────────┐
│ Your Worker (Layer 1) │
│ - Handles HTTP requests │
│ - Calls getSandbox() │
│ - Uses sandbox.exec(), writeFile(), etc│
└──────────────┬──────────────────────────┘
│ RPC via Durable Object
┌──────────────▼──────────────────────────┐
│ Durable Object (Layer 2) │
│ - Routes by sandbox ID │
│ - Maintains persistent identity │
│ - Geographic stickiness │
└──────────────┬──────────────────────────┘
│ Container API
┌──────────────▼──────────────────────────┐
│ Ubuntu Container (Layer 3) │
│ - Full Linux environment │
│ - Python 3.11, Node 20, Git, etc. │
│ - Filesystem: /workspace, /tmp, /home │
│ - Process isolation (VM-based) │
└─────────────────────────────────────────┘
重要なポイント:Workers は API ロジックを処理し(高速)、Durable Objects はリクエストをルーティングし(永続的な ID)、コンテナはコードを実行します(フル機能)。
コンテナのライフサイクルに関する重要事項(最も重要なセクション!)
コンテナの状態
┌─────────┐ First request ┌────────┐ ~10 min idle ┌──────┐
│ Not │ ───────────────>│ Active │ ─────────────> │ Idle │
│ Created │ │ │ │ │
└─────────┘ └───┬────┘ └──┬───┘
│ ^ │
│ │ New request │
│ └──────────────────────┘
│ │
▼ ▼
Files persist ALL FILES DELETED
Processes run ALL PROCESSES KILLED
State maintained ALL STATE RESET
最大の注意点:デフォルトでは一時的
コンテナがアクティブな間(最後のリクエストから約 10 分間):
- ✅
/workspace、/tmp、/home内のファイルは保持されます - ✅ バックグラウンドプロセスは実行を続けます
- ✅ シェル環境変数は維持されます
- ✅ セッションの作業ディレクトリは保持されます
コンテナがアイドル状態になると(非アクティブになった後):
- ❌ すべてのファイルが削除されます(ファイルシステム全体がリセットされます)
- ❌ すべてのプロセスが終了します
- ❌ すべてのシェル状態が失われます
- ⚠️ 次のリクエストでは新しいコンテナがゼロから作成されます
これは従来のサーバーとは異なります。Sandbox は設計上、一時的なものです。
永続性への対応
重要なデータの場合:外部ストレージを使用する
// Save to R2 before container goes idle
await sandbox.writeFile('/workspace/data.txt', content);
const fileData = await sandbox.readFile('/workspace/data.txt');
await env.R2.put('backup/data.txt', fileData);
// Restore on next request
const restored = await env.R2.get('backup/data.txt');
if (restored) {
await sandbox.writeFile('/workspace/data.txt', await restored.text());
}
ビルド成果物の場合:一時的なものとして扱うか、キャッシュを使用する
// Check if setup needed (handles cold starts)
const exists = await sandbox.readdir('/workspace/project').catch(() => null);
if (!exists) {
await sandbox.gitCheckout(repoUrl, '/workspace/project');
await sandbox.exec('npm install', { cwd: '/workspace/project' });
}
// Now safe to run build
await sandbox.exec('npm run build', { cwd: '/workspace/project' });
セッション管理(チャットエージェントのゲームチェンジャー)
セッションとは?
セッションは、1 つの Sandbox 内のbash シェルコンテキストです。ターミナルのタブのようなものです。
主な特性:
- 各セッションは個別の作業ディレクトリを持ちます
- セッション間で同じファイルシステムを共有します
- 同じセッション内では、コマンドをまたいで作業ディレクトリが保持されます
- 複数ステップのワークフローに最適です
パターン:チャットベースのコーディングエージェント
type ConversationState = {
sandboxId: string;
sessionId: string;
};
// First message: Create sandbox and session
const sandboxId = `user-${userId}`;
const sandbox = getSandbox(env.Sandbox, sandboxId);
const sessionId = await sandbox.createSession();
// Store in conversation state (database, KV, etc.)
await env.KV.put(`conversation:${conversationId}`, JSON.stringify({
sandboxId,
sessionId
}));
// Later messages: Reuse same session
const state = await env.KV.get(`conversation:${conversationId}`);
const { sandboxId, sessionId } = JSON.parse(state);
const sandbox = getSandbox(env.Sandbox, sandboxId);
// Commands run in same context
await sandbox.exec('cd /workspace/project', { session: sessionId });
await sandbox.exec('ls -la', { session: sessionId }); // Still in /workspace/project
await sandbox.exec('git status', { session: sessionId }); // Still in /workspace/project
セッションを使わない場合(よくある間違い)
// ❌ WRONG: Each command runs in separate session
await sandbox.exec('cd /workspace/project');
await sandbox.exec('ls'); // NOT in /workspace/project (different session)
パターン:並列実行
const session1 = await sandbox.createSession();
const session2 = await sandbox.createSession();
// Run different tasks simultaneously
await Promise.all([
sandbox.exec('python train_model.py', { session: session1 }),
sandbox.exec('node generate_reports.js', { session: session2 })
]);
Sandbox の命名戦略
ユーザーごとの Sandbox(永続的なワークスペース)
const sandbox = getSandbox(env.Sandbox, `user-${userId}`);
メリット:アクティブに使用している間(アイドル時間 10 分)、ユーザーの作業が保持されます デメリット:地理的な固定(最初のリクエストによって場所が決まります) 用途:インタラクティブなノートブック、IDE、永続的なワークスペース
セッションごとの Sandbox(毎回新規)
const sandboxId = `session-${Date.now()}-${crypto.randomUUID()}`;
const sandbox = getSandbox(env.Sandbox, sandboxId);
// Always destroy after use
await sandbox.destroy();
メリット:クリーンな環境で、状態が混在しません デメリット:リクエスト間の永続性がありません 用途:単発のコード実行、CI/CD、テスト
タスクごとの Sandbox(冪等で追跡可能)
const sandbox = getSandbox(env.Sandbox, `build-${repoName}-${commitSha}`);
メリット:再現可能、デバッグ可能、キャッシュ可能 デメリット:明示的なクリーンアップ戦略が必要です 用途:ビルドシステム、データパイプライン、自動化されたワークフロー
コア API リファレンス
Sandbox の取得
import { getSandbox } from '@cloudflare/sandbox';
const sandbox = getSandbox(env.Sandbox, 'unique-sandbox-id');
// Creates new sandbox if doesn't exist, or gets existing one
コマンドの実行
// Basic execution
const result = await sandbox.exec('python3 script.py');
console.log(result.stdout); // Standard output
console.log(result.stderr); // Standard error
console.log(result.exitCode); // Exit code (0 = success)
console.log(result.success); // Boolean (exitCode === 0)
// With options
const result = await sandbox.exec('npm install', {
cwd: '/workspace/project', // Working directory
timeout: 120000, // Timeout in ms (default: 30s)
session: sessionId, // Session ID
env: { NODE_ENV: 'production' } // Environment variables
});
// Always check exit codes!
if (!result.success) {
throw new Error(`Command failed: ${result.stderr}`);
}
ファイル操作
// Write file
await sandbox.writeFile('/workspace/data.txt', 'content');
// Read file
const content = await sandbox.readFile('/workspace/data.txt');
// Create directory
await sandbox.mkdir('/workspace/project', { recursive: true });
// List directory
const files = await sandbox.readdir('/workspace');
console.log(files); // ['data.txt', 'project']
// Delete file/directory
await sandbox.rm('/workspace/data.txt');
await sandbox.rm('/workspace/project', { recursive: true });
Git 操作
// Clone repository (optimized, faster than exec('git clone'))
await sandbox.gitCheckout(
'https://github.com/user/repo',
'/workspace/repo'
);
// Now use standard git commands
await sandbox.exec('git status', { cwd: '/workspace/repo' });
await sandbox.exec('git diff', { cwd: '/workspace/repo' });
コードインタープリター(Jupyter のような環境)
// Create Python context
const ctx = await sandbox.createCodeContext({ language: 'python' });
// Execute code - last expression auto-returned
const result = await sandbox.runCode(`
import pandas as pd
df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
df['a'].sum() # This value is automatically returned
`, { context: ctx });
console.log(result.results[0].text); // "6"
console.log(result.logs); // Output from print() statements
console.log(result.error); // Any errors
バックグラウンドプロセス
// Start long-running process
const proc = await sandbox.spawn('python server.py');
console.log(proc.pid);
// Check if still running
const running = await sandbox.isProcessRunning(proc.pid);
// Kill process
await sandbox.killProcess(proc.pid);
クリーンアップ
// Destroy sandbox permanently
await sandbox.destroy();
// All files deleted, container removed, cannot be recovered
重要なルール
常に実施すること
✅ 終了コードを確認する - if (!result.success) { handle error }
✅ 複数ステップのワークフローではセッションを使用する - 作業ディレクトリを保持します
✅ コールドスタートに対応する - ファイルがあると決めつけず、存在するか確認します
✅ タイムアウトを設定する - 長時間の処理でハングするのを防ぎます
✅ 一時的なサンドボックスを破棄する - 一時的なサンドボックスやセッションベースのサンドボックスをクリーンアップします
✅ 永続化には外部ストレージを使用する - 重要なデータには R2/KV/D1 を使用します
✅ ユーザー入力を検証する - コマンドインジェクションを防ぐため、exec() の前にサニタイズします
✅ Sandbox クラスをエクスポートする - export { Sandbox } from '@cloudflare/sandbox'
絶対にしないこと
❌ アイドル状態の後もファイルが保持されると思い込む - コンテナは約 10 分後にリセットされます
❌ 終了コードを無視する - 必ず result.success または result.exitCode を確認します
❌ セッションを使わずにコマンドを連結する - cd /dir の後に ls を実行しても機能しません
❌ サニタイズしていないユーザー入力を実行する - コードインタープリターを使用するか、十分に検証します
❌ nodejs_compat フラグを忘れる - wrangler.jsonc で必須です
❌ マイグレーションを省略する - Durable Objects にはマイグレーションエントリーが必要です
❌ プレビュー URL に .workers.dev を使用する - カスタムドメインが必要です
❌ サンドボックスを無制限に作成する - リークを防ぐため、一時的なものは破棄します
既知の問題の予防
このスキルは、文書化されている 10 件の問題を防ぎます。
問題 #1: nodejs_compat フラグがない
エラー: ReferenceError: fetch is not defined または Buffer is not defined
ソース: https://developers.cloudflare.com/sandbox/get-started/
発生する理由: SDK は、標準の Workers では利用できない Node.js API を必要とします
予防策: wrangler.jsonc に "compatibility_flags": ["nodejs_compat"] を追加します
問題 #2: マイグレーションがない
エラー: Error: Class 'Sandbox' not found
ソース: https://developers.cloudflare.com/durable-objects/
発生する理由: Durable Objects はマイグレーションを介して登録する必要があります
予防策: wrangler.jsonc に migrations 配列を含めます
問題 #3: ファイルの永続性を前提とする
エラー: 非アクティブ状態の後にファイルが消える ソース: https://developers.cloudflare.com/sandbox/concepts/sandboxes/ 発生する理由: コンテナは約 10 分後にアイドル状態になり、すべての状態がリセットされます 予防策: 外部ストレージ(R2/KV)を使用するか、リクエストごとにファイルの存在を確認します
問題 #4: セッションのディレクトリに関する混乱
エラー: コマンドが間違ったディレクトリで実行される
ソース: https://developers.cloudflare.com/sandbox/concepts/sessions/
発生する理由: 明示的に指定しない限り、exec() は毎回新しいセッションを使用します
予防策: createSession() でセッションを作成し、関連するすべてのコマンドに渡します
問題 #5: 終了コードを無視する
エラー: コマンドが失敗したのに成功したと思い込む
ソース: シェルのベストプラクティス
発生する理由: result.success または result.exitCode を確認していません
予防策: 必ず確認します: if (!result.success) throw new Error(result.stderr)
問題 #6: コールドスタートへの未対応
エラー: 依存関係がインストールされていないため、コマンドが失敗する ソース: https://developers.cloudflare.com/sandbox/concepts/sandboxes/ 発生する理由: アイドル期間の後にコンテナがリセットされます 予防策: コマンドを実行する前に、セットアップが必要か確認します
問題 #7: Docker が起動していない(ローカル開発)
エラー: ローカル開発中に Failed to build container
ソース: https://developers.cloudflare.com/sandbox/get-started/
発生する理由: ローカル開発には Docker デーモンが必要です
予防策: npm run dev の前に Docker Desktop が起動していることを確認します
問題 #8: バージョンの不一致(パッケージと Docker イメージ)
エラー: API メソッドが利用できない、または予期しない動作をする
ソース: GitHub issues
発生する理由: npm パッケージのバージョンと Docker イメージのバージョンが一致していません
予防策: @cloudflare/sandbox パッケージと cloudflare/sandbox イメージのバージョンを一致させます
問題 #9: 一時的なサンドボックスをクリーンアップしない
エラー: リソースの枯渇、予期しないコスト
ソース: リソース管理のベストプラクティス
発生する理由: サンドボックスを破棄せずに作成しています
予防策: 一時的なサンドボックスでは、finally ブロック内で await sandbox.destroy() を実行します
Issue #10:コマンドインジェクションの脆弱性
エラー:サニタイズされていないユーザー入力によるセキュリティ侵害
原因:セキュリティのベストプラクティス
発生理由:ユーザー入力を直接 exec() に渡しているためです
防止策:コードインタープリター API を使用するか、入力を十分に検証・サニタイズします
設定ファイルのリファレンス
wrangler.jsonc(完全な例)
{
"name": "my-sandbox-app",
"main": "src/index.ts",
"compatibility_date": "2025-10-29",
"compatibility_flags": ["nodejs_compat"],
"containers": [{
"class_name": "Sandbox",
"image": "cloudflare/sandbox:0.4.12",
"instance_type": "lite"
}],
"durable_objects": {
"bindings": [{
"class_name": "Sandbox",
"name": "Sandbox"
}]
},
"migrations": [{
"tag": "v1",
"new_sqlite_classes": ["Sandbox"]
}],
"env": {
"ANTHROPIC_API_KEY": {
"description": "Optional: For AI features"
}
},
"observability": {
"enabled": true
}
}
これらの設定の理由:
nodejs_compat:SDK の動作に必要ですcontainers.image:特定のバージョンを指定することで、一貫性を確保しますinstance_type: "lite":最小のインスタンスです。より多くのリソースが必要な場合は"large"に変更しますmigrations:Sandbox Durable Object クラスを登録しますobservability:デバッグ用のロギングを有効にします
Dockerfile(任意 — ローカル開発用)
ベースイメージを拡張する場合にのみ必要です。
FROM cloudflare/sandbox:0.4.12
# Install additional tools
RUN apt-get update && apt-get install -y \
ffmpeg \
imagemagick \
&& rm -rf /var/lib/apt/lists/*
# Expose port for preview URLs (local dev only)
EXPOSE 8080
よくあるパターン
パターン 1:単発のコード実行
export default {
async fetch(request: Request, env: Env) {
const { code, language } = await request.json();
// Create ephemeral sandbox
const sandboxId = `exec-${Date.now()}-${crypto.randomUUID()}`;
const sandbox = getSandbox(env.Sandbox, sandboxId);
try {
// Create code context
const ctx = await sandbox.createCodeContext({ language });
// Execute code safely
const result = await sandbox.runCode(code, {
context: ctx,
timeout: 10000
});
return Response.json({
result: result.results?.[0]?.text,
logs: result.logs,
error: result.error
});
} finally {
// Always cleanup
await sandbox.destroy();
}
}
};
使用する場面:コード実行用 API エンドポイント、コードプレイグラウンド、学習プラットフォーム
パターン 2:ユーザー用の永続的なワークスペース
export default {
async fetch(request: Request, env: Env) {
const userId = request.headers.get('X-User-ID');
const { command, sessionId: existingSession } = await request.json();
// User-specific sandbox (persists while active)
const sandbox = getSandbox(env.Sandbox, `user-${userId}`);
// Get or create session
let sessionId = existingSession;
if (!sessionId) {
sessionId = await sandbox.createSession();
}
// Execute command in persistent context
const result = await sandbox.exec(command, {
session: sessionId,
timeout: 30000
});
return Response.json({
sessionId, // Return for next request
output: result.stdout,
error: result.stderr,
success: result.success
});
}
};
使用する場面:対話型コーディング環境、ノートブック、IDE、開発ワークスペース
パターン 3:CI/CD ビルドパイプライン
async function runBuild(repoUrl: string, commit: string, env: Env) {
const sandboxId = `build-${repoUrl.split('/').pop()}-${commit}`;
const sandbox = getSandbox(env.Sandbox, sandboxId);
try {
// Clone repository
await sandbox.gitCheckout(repoUrl, '/workspace/repo');
// Checkout specific commit
await sandbox.exec(`git checkout ${commit}`, {
cwd: '/workspace/repo'
});
// Install dependencies
const install = await sandbox.exec('npm install', {
cwd: '/workspace/repo',
timeout: 180000 // 3 minutes
});
if (!install.success) {
throw new Error(`Install failed: ${install.stderr}`);
}
// Run build
const build = await sandbox.exec('npm run build', {
cwd: '/workspace/repo',
timeout: 300000 // 5 minutes
});
if (!build.success) {
throw new Error(`Build failed: ${build.stderr}`);
}
// Save artifacts to R2
const dist = await sandbox.exec('tar -czf dist.tar.gz dist', {
cwd: '/workspace/repo'
});
const artifact = await sandbox.readFile('/workspace/repo/dist.tar.gz');
await env.R2.put(`builds/${commit}.tar.gz`, artifact);
return { success: true, artifactKey: `builds/${commit}.tar.gz` };
} finally {
// Optional: Keep sandbox for debugging or destroy
// await sandbox.destroy();
}
}
使用する場面:ビルドシステム、テストパイプライン、デプロイの自動化
パターン 4:Claude Code を使用する AI エージェント
async function runClaudeCodeOnRepo(
repoUrl: string,
task: string,
env: Env
): Promise<{ diff: string; logs: string }> {
const sandboxId = `claude-${Date.now()}`;
const sandbox = getSandbox(env.Sandbox, sandboxId);
try {
// Clone repository
await sandbox.gitCheckout(repoUrl, '/workspace/repo');
// Run Claude Code CLI with secure environment injection
// ⚠️ SECURITY: Use env option instead of shell export to prevent key exposure in logs
const result = await sandbox.exec(
`claude -p "${task}" --permission-mode acceptEdits`,
{
cwd: '/workspace/repo',
timeout: 300000, // 5 minutes
env: {
ANTHROPIC_API_KEY: env.ANTHROPIC_API_KEY
}
}
);
// Get diff of changes
const diff = await sandbox.exec('git diff', {
cwd: '/workspace/repo'
});
return {
diff: diff.stdout,
logs: result.stdout
};
} finally {
await sandbox.destroy();
}
}
使用する場面:コードの自動リファクタリング、コード生成、AI を活用した開発
同梱リソースの使用
スクリプト(scripts/)
setup-sandbox-binding.sh- 対話形式での wrangler.jsonc 設定test-sandbox.ts- Sandbox のセットアップをテストする検証スクリプト
使用例:
# Setup wrangler config
./scripts/setup-sandbox-binding.sh
# Test sandbox
npx tsx scripts/test-sandbox.ts
リファレンス(references/)
references/persistence-guide.md- コンテナのライフサイクルと永続性の詳細な解説references/session-management.md- 高度なセッションパターンとベストプラクティスreferences/common-errors.md- 解決策を含むエラーの完全な一覧references/naming-strategies.md- さまざまなユースケースに応じた Sandbox ID の選び方
Claude がこれらを読み込むタイミング:
- 状態の問題やコールドスタートをデバッグするときは、
persistence-guide.mdを読み込みます - 複数ステップのワークフローやチャットエージェントを構築するときは、
session-management.mdを読み込みます - 特定のエラーが発生したときは、
common-errors.mdを読み込みます - Sandbox のアーキテクチャを設計するときは、
naming-strategies.mdを読み込みます
高度なトピック
地理的な分散
Sandbox ID への最初のリクエストによって、その地理的な配置場所が決まります(Durable Objects 経由)。
グローバルアプリの場合:
// Option 1: Multiple sandboxes per user (better latency)
const region = request.cf?.colo || 'default';
const sandbox = getSandbox(env.Sandbox, `user-${userId}-${region}`);
// Option 2: Single sandbox (simpler, higher latency for distant users)
const sandbox = getSandbox(env.Sandbox, `user-${userId}`);
エラー処理の戦略
async function safeSandboxExec(
sandbox: Sandbox,
cmd: string,
options?: any
) {
try {
const result = await sandbox.exec(cmd, {
...options,
timeout: options?.timeout || 30000
});
if (!result.success) {
console.error(`Command failed: ${cmd}`, {
exitCode: result.exitCode,
stderr: result.stderr
});
return {
success: false,
error: result.stderr,
exitCode: result.exitCode
};
}
return {
success: true,
output: result.stdout,
exitCode: 0
};
} catch (error) {
console.error(`Sandbox error:`, error);
return {
success: false,
error: error.message,
exitCode: -1
};
}
}
セキュリティの強化
// Input validation
function sanitizeCommand(input: string): string {
const dangerous = ['rm -rf', '$(', '`', '&&', '||', ';', '|'];
for (const pattern of dangerous) {
if (input.includes(pattern)) {
throw new Error(`Dangerous pattern detected: ${pattern}`);
}
}
return input;
}
// Use code interpreter instead of direct exec for untrusted code
async function executeUntrustedCode(code: string, sandbox: Sandbox) {
const ctx = await sandbox.createCodeContext({ language: 'python' });
return await sandbox.runCode(code, { context: ctx, timeout: 10000 });
}
依存関係
必須:
@cloudflare/[email protected]- Sandbox SDKwrangler@latest- デプロイ用 CLI- Docker Desktop - ローカル開発専用
任意:
@anthropic-ai/sdk- AI 機能用@cloudflare/workers-types- TypeScript 型定義
公式ドキュメント
- Cloudflare Sandboxes:https://developers.cloudflare.com/sandbox/
- アーキテクチャガイド:https://developers.cloudflare.com/sandbox/concepts/architecture/
- API リファレンス:https://developers.cloudflare.com/sandbox/api-reference/
- Durable Objects:https://developers.cloudflare.com/durable-objects/
- GitHub SDK:https://github.com/cloudflare/sandbox-sdk
パッケージのバージョン(2025-10-29 に検証済み)
{
"dependencies": {
"@cloudflare/sandbox": "^0.4.12"
},
"devDependencies": {
"wrangler": "^3.80.0",
"@cloudflare/workers-types": "^4.20241106.0"
}
}
Docker イメージ:cloudflare/sandbox:0.4.12
本番環境での例
このスキルは、Cloudflare の公式チュートリアルに基づいています:
- Claude Code の統合:https://developers.cloudflare.com/sandbox/tutorials/claude-code/
- AI コード実行ツール:https://developers.cloudflare.com/sandbox/tutorials/ai-code-executor/
- 所要時間:約 15 分(セットアップ)+約 5 分(初回デプロイ)
- エラー:0 件(既知の問題 10 件をすべて防止)
- 検証:✅ Python、Node.js、Git、バックグラウンドプロセス、セッションでテスト済み
トラブルシューティング
問題:「Class 'Sandbox' not found」
解決策:wrangler.jsonc に migrations を追加し、Worker 内に export { Sandbox } があることを確認します
問題:時間が経つとファイルが消える
解決策:コンテナは約10分後にアイドル状態になります。永続化にはR2/KVを使用するか、環境を再構築してください。
問題:コマンドが間違ったディレクトリで実行される
解決策:createSession()でセッションを作成し、関連するすべてのコマンドにsessionIdを渡してください。
問題:ローカル開発中にDockerエラーが発生する
解決策:npm run devを実行する前に、Docker Desktopが起動していることを確認してください。
問題:「fetch is not defined」
解決策:wrangler.jsoncに"compatibility_flags": ["nodejs_compat"]を追加してください。
セットアップ完了チェックリスト
-
npm install @cloudflare/sandbox@latest - compatibility_flagsに
nodejs_compatを追加する - 正しいイメージバージョンを指定してコンテナ設定を追加する
- Durable Objectsのバインディングを追加する
- Sandboxクラスのマイグレーションを追加する
- WorkerでSandboxクラスをエクスポートする:
export { Sandbox } from '@cloudflare/sandbox' - Docker Desktopが起動している(ローカル開発のみ)
- シンプルなexecコマンドでテストする
- 終了コードが確認されていることを検証する
- 一時的なサンドボックスのクリーンアップを実装する
- コールドスタート時の動作をテストする
質問や問題がありますか?
- 個別のエラー解決策については、
references/common-errors.mdを確認してください。 - wrangler.jsoncの設定ですべての手順を確認してください。
- 公式ドキュメントを確認してください:https://developers.cloudflare.com/sandbox/
- ローカル開発用にDockerが起動していることを確認してください。
- パッケージのバージョンがDockerイメージのバージョンと一致していることを確認してください。