添加中文文档

This commit is contained in:
2026-05-12 13:14:17 +00:00
parent 61d7ca6bba
commit 38bb076ac6
24 changed files with 6876 additions and 0 deletions

359
docs/zh/docker-sandboxes.md Normal file
View File

@@ -0,0 +1,359 @@
# 在 Docker 沙盒中运行 NanoClaw手动设置
本指南介绍如何从头开始在 [Docker 沙盒](https://docs.docker.com/ai/sandboxes/)中设置 NanoClaw——无需安装脚本无需预构建的 fork。你将克隆上游仓库应用必要的补丁并在完全的 hypervisor 级别隔离下运行 agent智能体
## 架构
```
宿主机 (macOS / Windows WSL)
└── Docker 沙盒 (带隔离内核的微 VM)
├── NanoClaw 进程 (Node.js)
│ ├── 频道适配器 (WhatsApp, Telegram 等)
│ └── 容器启动器 → 嵌套 Docker 守护进程
└── Docker-in-Docker
└── nanoclaw-agent 容器
└── Claude Agent SDK
```
每个 agent 在自己的容器中运行,位于一个与你的宿主机完全隔离的微 VM 内。两层隔离:每个 agent 的容器 + VM 边界。
沙盒在 `host.docker.internal:3128` 提供一个 MITM 代理,处理网络访问并自动注入你的 Anthropic API 密钥。
> **注意:** 本指南基于在 macOSApple Silicon上使用 WhatsApp 验证过的设置。其他频道Telegram、Slack 等和环境Windows WSL可能需要针对其特定 HTTP/WebSocket 客户端添加额外的代理补丁。核心补丁容器运行器、凭据代理、Dockerfile普遍适用——频道特定的代理配置各有不同。
## 前提条件
- **Docker Desktop v4.40+** 支持沙盒
- **Anthropic API 密钥**(沙盒代理管理注入)
- 对于 **Telegram**:来自 [@BotFather](https://t.me/BotFather) 的 bot token 和你的 chat ID
- 对于 **WhatsApp**:一部安装了 WhatsApp 的手机
验证沙盒支持:
```bash
docker sandbox version
```
## 步骤 1创建沙盒
在你的宿主机上:
```bash
# 创建工作区目录
mkdir -p ~/nanoclaw-workspace
# 创建带工作区挂载的 shell 沙盒
docker sandbox create shell ~/nanoclaw-workspace
```
如果你使用 WhatsApp配置代理绕过使 WhatsApp 的 Noise 协议不被 MITM 检查:
```bash
docker sandbox network proxy shell-nanoclaw-workspace \
--bypass-host web.whatsapp.com \
--bypass-host "*.whatsapp.com" \
--bypass-host "*.whatsapp.net"
```
Telegram 不需要代理绕过。
进入沙盒:
```bash
docker sandbox run shell-nanoclaw-workspace
```
## 步骤 2安装前提依赖
在沙盒内:
```bash
sudo apt-get update && sudo apt-get install -y build-essential python3
npm config set strict-ssl false
```
## 步骤 3克隆并安装 NanoClaw
NanoClaw 必须位于工作区目录内——Docker-in-Docker 只能从共享的工作区路径进行 bind-mount。
```bash
# 先克隆到家目录virtiofs 可能在克隆期间损坏 git pack 文件)
cd ~
git clone https://github.com/nanocoai/nanoclaw.git
# 替换为你的工作区路径(你传递给 `docker sandbox create` 的宿主机路径)
WORKSPACE=/Users/you/nanoclaw-workspace
# 移入工作区,以便 DinD 挂载生效
mv nanoclaw "$WORKSPACE/nanoclaw"
cd "$WORKSPACE/nanoclaw"
# 安装依赖
pnpm install
pnpm install https-proxy-agent
```
## 步骤 4应用代理和沙盒补丁
NanoClaw 需要多个补丁才能在 Docker 沙盒内工作。这些补丁处理代理路由、CA 证书和 Docker-in-Docker 挂载限制。
### 4a. Dockerfile——用于容器镜像构建的代理参数
`sandbox 内的 docker build` 会因为沙盒的 MITM 代理提供自己的证书而出现 `SELF_SIGNED_CERT_IN_CHAIN` 失败。向 `container/Dockerfile` 添加代理构建参数:
`FROM` 行之后添加这些行:
```dockerfile
# 接受代理构建参数
ARG http_proxy
ARG https_proxy
ARG no_proxy
ARG NODE_EXTRA_CA_CERTS
ARG npm_config_strict_ssl=true
RUN npm config set strict-ssl ${npm_config_strict_ssl}
```
并在 `RUN pnpm install` 行之后:
```dockerfile
RUN npm config set strict-ssl true
```
### 4b. 构建脚本——转发代理参数
补丁 `container/build.sh`,将代理环境变量传递给 `docker build`
`docker build` 命令中添加这些 `--build-arg` 标志:
```bash
--build-arg http_proxy="${http_proxy:-$HTTP_PROXY}" \
--build-arg https_proxy="${https_proxy:-$HTTPS_PROXY}" \
--build-arg no_proxy="${no_proxy:-$NO_PROXY}" \
--build-arg npm_config_strict_ssl=false \
```
### 4c. 容器运行器——代理转发、CA 证书挂载、/dev/null 修复
`src/container-runner.ts` 的三处更改:
**替换 `/dev/null` 影子挂载。** 沙盒拒绝 `/dev/null` bind mount。找到 `.env` 被影子挂载到 `/dev/null` 的位置,将其替换为一个空文件:
```typescript
// 创建一个空文件来影子 .envDocker 沙盒拒绝 /dev/null 挂载)
const emptyEnvPath = path.join(DATA_DIR, 'empty-env');
if (!fs.existsSync(emptyEnvPath)) fs.writeFileSync(emptyEnvPath, '');
// 在挂载中使用 emptyEnvPath 代替 '/dev/null'
```
**将代理环境变量转发**到生成的 agent 容器。为 `HTTP_PROXY``HTTPS_PROXY``NO_PROXY` 及其小写变体添加 `-e` 标志。
**挂载 CA 证书。** 如果设置了 `NODE_EXTRA_CA_CERTS``SSL_CERT_FILE`,将证书复制到项目目录并挂载到 agent 容器中:
```typescript
const caCertSrc = process.env.NODE_EXTRA_CA_CERTS || process.env.SSL_CERT_FILE;
if (caCertSrc) {
const certDir = path.join(DATA_DIR, 'ca-cert');
fs.mkdirSync(certDir, { recursive: true });
fs.copyFileSync(caCertSrc, path.join(certDir, 'proxy-ca.crt'));
// 挂载certDir -> /workspace/ca-cert只读
// 在容器中设置 NODE_EXTRA_CA_CERTS=/workspace/ca-cert/proxy-ca.crt
}
```
### 4d. 容器运行时——防止自我终止
`src/container-runtime.ts` 中,`cleanupOrphans()` 函数通过 `nanoclaw-` 前缀匹配容器。在沙盒内,沙盒容器本身可能匹配(例如 `nanoclaw-docker-sandbox`)。过滤掉当前主机名:
```typescript
// 在 cleanupOrphans() 中,从要停止的容器列表中过滤掉 os.hostname()
```
### 4e. 凭据代理——通过 MITM 代理路由
`src/credential-proxy.ts` 中,上游 API 请求需要通过沙盒代理。向出站请求添加 `HttpsProxyAgent`
```typescript
import { HttpsProxyAgent } from 'https-proxy-agent';
const proxyUrl = process.env.HTTPS_PROXY || process.env.https_proxy;
const upstreamAgent = proxyUrl ? new HttpsProxyAgent(proxyUrl) : undefined;
// 将 upstreamAgent 传递给 https.request() 选项
```
### 4f. 安装脚本——代理构建参数
补丁 `setup/container.ts`,传递与 `build.sh`(步骤 4b相同的代理 `--build-arg` 标志。
## 步骤 5构建
```bash
pnpm run build
bash container/build.sh
```
## 步骤 6添加频道
### Telegram
```bash
# 应用 Telegram 技能
pnpm exec tsx scripts/apply-skill.ts .claude/skills/add-telegram
# 应用技能后重建
pnpm run build
# 配置 .env
cat > .env << EOF
TELEGRAM_BOT_TOKEN=<your-token-from-botfather>
ASSISTANT_NAME=nanoclaw
ANTHROPIC_API_KEY=proxy-managed
EOF
mkdir -p data/env && cp .env data/env/env
# 注册你的聊天
pnpm exec tsx setup/index.ts --step register \
--jid "tg:<your-chat-id>" \
--name "My Chat" \
--trigger "@nanoclaw" \
--folder "telegram_main" \
--channel telegram \
--assistant-name "nanoclaw" \
--is-main \
--no-trigger-required
```
**查找你的 chat ID** 向你的 bot 发送任意消息,然后:
```bash
curl -s --proxy $HTTPS_PROXY "https://api.telegram.org/bot<TOKEN>/getUpdates" | python3 -m json.tool
```
**群组中的 Telegram**@BotFather 中禁用群组隐私(`/mybots` > Bot Settings > Group Privacy > Turn off然后移除并重新添加 bot。
**重要提示:** 如果 Telegram 技能创建了 `src/channels/telegram.ts`,你需要为代理支持打补丁。添加一个 `HttpsProxyAgent` 并通过 `baseFetchConfig.agent` 将其传递给 grammy 的 `Bot` 构造函数。然后重建。
### WhatsApp
确保你已先在[步骤 1](#步骤-1创建沙盒)中配置了代理绕过。
```bash
# 应用 WhatsApp 技能
pnpm exec tsx scripts/apply-skill.ts .claude/skills/add-whatsapp
# 重建
pnpm run build
# 配置 .env
cat > .env << EOF
ASSISTANT_NAME=nanoclaw
ANTHROPIC_API_KEY=proxy-managed
EOF
mkdir -p data/env && cp .env data/env/env
# 认证(选择一种):
# QR 码——用 WhatsApp 相机扫描:
pnpm exec tsx src/whatsapp-auth.ts
# 或配对码——在 WhatsApp > 已关联设备 > 通过电话号码关联中输入代码:
pnpm exec tsx src/whatsapp-auth.ts --pairing-code --phone <phone-number-no-plus>
# 注册你的聊天JID = 你的电话号码 + @s.whatsapp.net
pnpm exec tsx setup/index.ts --step register \
--jid "<phone>@s.whatsapp.net" \
--name "My Chat" \
--trigger "@nanoclaw" \
--folder "whatsapp_main" \
--channel whatsapp \
--assistant-name "nanoclaw" \
--is-main \
--no-trigger-required
```
**重要提示:** WhatsApp 技能文件(`src/channels/whatsapp.ts``src/whatsapp-auth.ts`)也需要代理补丁——为 WebSocket 连接添加 `HttpsProxyAgent` 以及一个支持代理的版本获取。然后重建。
### 两个频道
应用两个技能,为两者打代理补丁,合并 `.env` 变量,并分别注册每个聊天。
## 步骤 7运行
```bash
pnpm start
```
你不需要手动设置 `ANTHROPIC_API_KEY`。沙盒代理拦截请求,并自动将 `proxy-managed` 替换为你的真实密钥。
## 网络细节
### 代理如何工作
沙盒的所有流量通过宿主机代理路由,地址为 `host.docker.internal:3128`
```
Agent 容器 → DinD 网桥 → 沙盒 VM → host.docker.internal:3128 → 宿主机代理 → api.anthropic.com
```
**"绕过"并不意味着流量跳过代理。** 它意味着代理在不做 MITM 检查的情况下传递流量。Node.js 不会自动使用 `HTTP_PROXY` 环境变量——你需要在每个 HTTP/WebSocket 客户端中显式配置 `HttpsProxyAgent`
### DinD 挂载的共享路径
只有工作区目录可用于 Docker-in-Docker bind mount。工作区之外的路径会失败并显示"path not shared"
- `/dev/null` → 改为项目目录中的空文件
- `/usr/local/share/ca-certificates/` → 将证书复制到项目目录
- `/home/agent/` → 改为克隆到工作区
### Git clone 和 virtiofs
工作区通过 virtiofs 挂载。Git 的 pack 文件处理在 virtiofs 上可能在 clone 期间损坏。解决方法:先 clone 到 `/home/agent`,然后 `mv` 到工作区。
## 故障排查
### pnpm install 失败并出现 SELF_SIGNED_CERT_IN_CHAIN
```bash
npm config set strict-ssl false
```
### 容器构建失败并出现代理错误
```bash
docker build \
--build-arg http_proxy=$http_proxy \
--build-arg https_proxy=$https_proxy \
-t nanoclaw-agent:latest container/
```
### Agent 容器失败并出现 "path not shared"
所有 bind-mounted 路径必须在工作区目录下。检查:
- NanoClaw 是否克隆到了工作区?(不是 `/home/agent/`
- CA 证书是否复制到了项目根目录?
- 空的 `.env` 影子文件是否已创建?
### Agent 容器无法访问 Anthropic API
验证代理环境变量是否转发到了 agent 容器。检查容器日志中的 `HTTP_PROXY=http://host.docker.internal:3128`
### WhatsApp 错误 405
版本获取返回了过时的版本。确保已应用支持代理的 `fetchWaVersionViaProxy` 补丁——它通过 `HttpsProxyAgent` 获取 `sw.js` 并解析 `client_revision`
### WhatsApp 立即显示 "Connection failed"
代理绕过未配置。从**宿主机**运行:
```bash
docker sandbox network proxy <sandbox-name> \
--bypass-host web.whatsapp.com \
--bypass-host "*.whatsapp.com" \
--bypass-host "*.whatsapp.net"
```
### Telegram bot 不接收消息
1. 检查 grammy 代理补丁已应用(在 `src/channels/telegram.ts` 中查找 `HttpsProxyAgent`
2. 如果在群组中使用,检查 @BotFather 中群组隐私已禁用
### Git clone 失败并出现 "inflate: data stream error"
先 clone 到非工作区路径,然后移动:
```bash
cd ~ && git clone https://github.com/nanocoai/nanoclaw.git && mv nanoclaw /path/to/workspace/nanoclaw
```
### WhatsApp QR 码不显示
在沙盒内以交互方式运行认证命令(不通过 `docker sandbox exec` 管道):
```bash
docker sandbox run shell-nanoclaw-workspace
# 然后在沙盒内:
pnpm exec tsx src/whatsapp-auth.ts
```