docker-sandbox
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDocker Sandbox for Agent Tools
面向Agent工具的Docker沙箱
Isolated execution of , , and other agent tools using Docker Desktop's (v0.11.0+). Uses existing Claude Max and ChatGPT Pro subscriptions — no API key billing.
claudecodexdocker sandboxADR: ADR-0023
使用Docker Desktop的(v0.11.0及以上版本)实现、和其他Agent工具的隔离执行。可使用现有的Claude Max和ChatGPT Pro订阅,无需额外支付API密钥费用。
docker sandboxclaudecodexADR: ADR-0023
Prerequisites
前置要求
- Docker Desktop running (OrbStack works)
- returns ≥0.11.0
docker sandbox version - Auth secrets stored in :
agent-secrets- — from
claude_setup_token(1-year token, Max subscription)claude setup-token - — contents of
codex_auth_json(ChatGPT Pro subscription)~/.codex/auth.json
- Docker Desktop处于运行状态(OrbStack也可)
- 返回版本≥0.11.0
docker sandbox version - 身份验证密钥存储在中:
agent-secrets- — 来自
claude_setup_token(有效期1年的令牌,需Max订阅)claude setup-token - —
codex_auth_json的文件内容(需ChatGPT Pro订阅)~/.codex/auth.json
Quick Reference
快速参考
bash
undefinedbash
undefinedCreate a sandbox
创建一个沙箱
docker sandbox create --name my-sandbox claude /path/to/project
docker sandbox create --name my-sandbox claude /path/to/project
Run a command in it
在沙箱中运行命令
docker sandbox exec -e "CLAUDE_CODE_OAUTH_TOKEN=..." -w /path/to/project my-sandbox
claude -p "implement the feature" --output-format text --dangerously-skip-permissions
claude -p "implement the feature" --output-format text --dangerously-skip-permissions
docker sandbox exec -e "CLAUDE_CODE_OAUTH_TOKEN=..." -w /path/to/project my-sandbox
claude -p "implement the feature" --output-format text --dangerously-skip-permissions
claude -p "implement the feature" --output-format text --dangerously-skip-permissions
List sandboxes
列出所有沙箱
docker sandbox ls
docker sandbox ls
Remove
删除沙箱
docker sandbox rm my-sandbox
undefineddocker sandbox rm my-sandbox
undefinedAuth Setup (One-Time)
身份验证配置(仅需一次)
Claude (Max subscription)
Claude(需Max订阅)
Run interactively on the host (needs browser for OAuth):
bash
claude setup-tokenThis opens a browser, completes OAuth, and prints a token like . Valid for 1 year.
sk-ant-oat01-...Store it:
bash
secrets add claude_setup_token --value "sk-ant-oat01-..."Use in sandbox:
bash
TOKEN=$(secrets lease claude_setup_token --ttl 1h --raw)
docker sandbox exec -e "CLAUDE_CODE_OAUTH_TOKEN=$TOKEN" my-sandbox claude auth status在主机上交互式运行(需要浏览器完成OAuth):
bash
claude setup-token该命令会打开浏览器完成OAuth验证,并输出格式为的令牌,有效期为1年。
sk-ant-oat01-...存储令牌:
bash
secrets add claude_setup_token --value "sk-ant-oat01-..."在沙箱中使用:
bash
TOKEN=$(secrets lease claude_setup_token --ttl 1h --raw)
docker sandbox exec -e "CLAUDE_CODE_OAUTH_TOKEN=$TOKEN" my-sandbox claude auth status→ loggedIn: true, authMethod: oauth_token
→ loggedIn: true, authMethod: oauth_token
undefinedundefinedCodex (ChatGPT Pro subscription)
Codex(需ChatGPT Pro订阅)
Authenticate codex locally (needs browser):
bash
codex # Select "Sign in with ChatGPT", complete OAuthThe auth file at is portable (not host-tied). Store it:
~/.codex/auth.jsonbash
secrets add codex_auth_json --value "$(cat ~/.codex/auth.json)"Inject into sandbox:
bash
AUTH=$(secrets lease codex_auth_json --ttl 1h --raw)
docker sandbox exec my-sandbox bash -c "mkdir -p ~/.codex && cat > ~/.codex/auth.json << 'EOF'
${AUTH}
EOF"在本地完成codex身份验证(需要浏览器):
bash
codex # 选择"Sign in with ChatGPT",完成OAuth验证位于的验证文件是可移植的(不绑定主机),存储该文件:
~/.codex/auth.jsonbash
secrets add codex_auth_json --value "$(cat ~/.codex/auth.json)"注入到沙箱中:
bash
AUTH=$(secrets lease codex_auth_json --ttl 1h --raw)
docker sandbox exec my-sandbox bash -c "mkdir -p ~/.codex && cat > ~/.codex/auth.json << 'EOF'
${AUTH}
EOF"Token Refresh
令牌刷新
| Token | Lifetime | Refresh |
|---|---|---|
| 1 year | Run |
| Until subscription change | Re-run |
| 令牌 | 有效期 | 刷新方式 |
|---|---|---|
| 1年 | 重新运行 |
| 到订阅变更为止 | 如果验证失败则重新运行 |
Agent Loop Integration
Agent循环集成
Pre-warm Pattern
预热模式
Create sandbox(es) at loop start, reuse for all stories, destroy at loop end.
PLANNER (loop start)
├── docker sandbox create --name loop-{loopId}-claude claude {workDir}
├── docker sandbox create --name loop-{loopId}-codex codex {workDir} # if needed
└── inject auth into both
IMPLEMENTOR / TEST-WRITER / REVIEWER (per story)
└── docker sandbox exec -w {workDir} -e CLAUDE_CODE_OAUTH_TOKEN=... loop-{loopId}-{tool} \
{tool command}
# ~90ms overhead, workspace changes visible on host immediately
COMPLETE / CANCEL (loop end)
├── docker sandbox rm loop-{loopId}-claude
└── docker sandbox rm loop-{loopId}-codex在循环启动时创建沙箱,所有任务复用沙箱,循环结束时销毁沙箱。
PLANNER (循环启动)
├── docker sandbox create --name loop-{loopId}-claude claude {workDir}
├── docker sandbox create --name loop-{loopId}-codex codex {workDir} # 按需创建
└── 向两个沙箱注入验证信息
IMPLEMENTOR / TEST-WRITER / REVIEWER (每个任务)
└── docker sandbox exec -w {workDir} -e CLAUDE_CODE_OAUTH_TOKEN=... loop-{loopId}-{tool} \
{tool command}
# ~90ms开销,工作区变更会立即同步到主机
COMPLETE / CANCEL (循环结束)
├── docker sandbox rm loop-{loopId}-claude
└── docker sandbox rm loop-{loopId}-codexTiming
耗时说明
| Operation | Time |
|---|---|
| Create (cached image) | ~14s |
| Exec (warm sandbox) | ~90ms |
| Stop | ~11s |
| Remove | ~150ms |
Net overhead per loop: ~14s create + ~90ms × N stories = negligible for loops running 5-10 stories at 5-15min each.
| 操作 | 耗时 |
|---|---|
| 创建(使用缓存镜像) | ~14s |
| 执行(预热后的沙箱) | ~90ms |
| 停止 | ~11s |
| 删除 | ~150ms |
每个循环的总开销:~14s创建时间 + ~90ms × 任务数,对于单次运行5-10个任务、总时长5-15分钟的循环来说开销可忽略。
Workspace Mount
工作区挂载
The workspace is bidirectional — same path on host and in sandbox:
- File created in sandbox → visible on host at same path
- File created on host → visible in sandbox
- Git operations work normally (host sees sandbox changes, sandbox sees host commits)
工作区是双向同步的,主机和沙箱中的路径一致:
- 沙箱中创建的文件 → 主机同路径下可见
- 主机中创建的文件 → 沙箱中可见
- Git操作可正常运行(主机可见沙箱的变更,沙箱可见主机的提交)
Sandbox Templates
沙箱模板
| Template | Tools Included |
|---|---|
| claude 2.1.42, git, node 20, npm |
| codex 0.101.0, git, node 20, npm |
Neither includes . If bun is needed, use host-mode fallback or install it post-create.
bun| 模板 | 内置工具 |
|---|---|
| claude 2.1.42, git, node 20, npm |
| codex 0.101.0, git, node 20, npm |
两个模板都不包含,如果需要使用bun,可以降级到主机模式或者在沙箱创建后手动安装。
bunEnv Vars
环境变量
Pass via :
docker sandbox exec -ebash
docker sandbox exec \
-e "CLAUDE_CODE_OAUTH_TOKEN=$TOKEN" \
-e "NODE_ENV=development" \
-w /path/to/project \
my-sandbox \
claude -p "prompt" --output-format text --dangerously-skip-permissions通过传入:
docker sandbox exec -ebash
docker sandbox exec \
-e "CLAUDE_CODE_OAUTH_TOKEN=$TOKEN" \
-e "NODE_ENV=development" \
-w /path/to/project \
my-sandbox \
claude -p "prompt" --output-format text --dangerously-skip-permissionsNetwork Control
网络控制
Sandboxes have network access by default. Restrict with proxy rules:
bash
undefined沙箱默认开放网络访问,可通过代理规则限制访问:
bash
undefinedAllow only API endpoints
仅允许访问API端点
docker sandbox network proxy my-sandbox --policy deny
docker sandbox network proxy my-sandbox --allow-host api.anthropic.com
docker sandbox network proxy my-sandbox --allow-host api.openai.com
undefineddocker sandbox network proxy my-sandbox --policy deny
docker sandbox network proxy my-sandbox --allow-host api.anthropic.com
docker sandbox network proxy my-sandbox --allow-host api.openai.com
undefinedFallback to Host Mode
降级到主机模式
If Docker is unavailable:
bash
undefined如果Docker不可用:
bash
undefinedCheck availability
检查可用性
docker info >/dev/null 2>&1 || echo "Docker not available"
docker info >/dev/null 2>&1 || echo "Docker not available"
Force host mode
强制启用主机模式
export AGENT_LOOP_HOST=1
undefinedexport AGENT_LOOP_HOST=1
undefinedSaving Custom Templates
保存自定义模板
If you install additional tools in a sandbox, save it as a template:
bash
undefined如果你在沙箱中安装了额外工具,可以将其保存为模板:
bash
undefinedInstall tools
安装工具
docker sandbox exec my-sandbox bash -c 'npm i -g @anthropic-ai/claude-code @openai/codex'
docker sandbox exec my-sandbox bash -c 'npm i -g @anthropic-ai/claude-code @openai/codex'
Save as template
保存为模板
docker sandbox save my-sandbox my-agent-template:v1
docker sandbox save my-sandbox my-agent-template:v1
Use the template for future sandboxes
后续创建沙箱时使用该模板
docker sandbox create --name fast-sandbox -t my-agent-template:v1 claude /path/to/project
undefineddocker sandbox create --name fast-sandbox -t my-agent-template:v1 claude /path/to/project
undefinedImplementation in utils.ts
在utils.ts中实现
New Functions (ADR-0023)
新增函数(ADR-0023)
typescript
// Create sandbox for a loop
async function createLoopSandbox(
loopId: string,
tool: "claude" | "codex",
workDir: string
): Promise<string> // returns sandbox name
// Execute command in existing sandbox
async function execInSandbox(
sandboxName: string,
command: string[],
opts: { env?: Record<string, string>; workDir?: string; timeout?: number }
): Promise<{ exitCode: number; output: string }>
// Destroy loop sandbox(es)
async function destroyLoopSandbox(loopId: string): Promise<void>typescript
// 为循环创建沙箱
async function createLoopSandbox(
loopId: string,
tool: "claude" | "codex",
workDir: string
): Promise<string> // 返回沙箱名称
// 在现有沙箱中执行命令
async function execInSandbox(
sandboxName: string,
command: string[],
opts: { env?: Record<string, string>; workDir?: string; timeout?: number }
): Promise<{ exitCode: number; output: string }>
// 销毁循环关联的沙箱
async function destroyLoopSandbox(loopId: string): Promise<void>Replacing spawnTool()
替换spawnTool()
Current in implement.ts checks and . Update it to:
spawnTool()AGENT_LOOP_HOSTisDockerAvailable()- Check if sandbox exists (created by planner)
loop-{loopId}-{tool} - If yes → with auth env vars
execInSandbox() - If no → fall back to (current host-mode behavior)
spawnToolHost()
当前implement.ts中的会检查和,将其更新为如下逻辑:
spawnTool()AGENT_LOOP_HOSTisDockerAvailable()- 检查是否存在沙箱(由规划器创建)
loop-{loopId}-{tool} - 如果存在 → 传入验证环境变量调用
execInSandbox() - 如果不存在 → 降级到(当前的主机模式逻辑)
spawnToolHost()
Troubleshooting
问题排查
"Not logged in" in sandbox
沙箱中提示“未登录”
Auth not injected. Check:
bash
docker sandbox exec my-sandbox bash -c 'claude auth status'
docker sandbox exec my-sandbox bash -c 'cat ~/.codex/auth.json | head -3'验证信息未注入,检查:
bash
docker sandbox exec my-sandbox bash -c 'claude auth status'
docker sandbox exec my-sandbox bash -c 'cat ~/.codex/auth.json | head -3'Sandbox creation slow
沙箱创建缓慢
First pull downloads ~500MB image. Subsequent creates use cached image (~14s). Use to create a pre-configured template.
docker sandbox save首次拉取需要下载约500MB的镜像,后续创建会使用缓存镜像(约14s)。可使用创建预配置的模板加快速度。
docker sandbox saveFile not visible between host and sandbox
主机和沙箱之间文件不可见
Only the workspace path is mounted. Files outside the workspace directory are not shared.
只有工作区路径会被挂载,工作区目录外的文件不会共享。
"docker sandbox: command not found"
提示“docker sandbox: command not found”
Docker Desktop must be running. Check version: . Requires Docker Desktop 4.40+ with sandbox extension.
docker sandbox version必须运行Docker Desktop,检查版本:。需要安装了沙箱扩展的Docker Desktop 4.40及以上版本。
docker sandbox version