1. OpenClaw Docker 手工部署到底难在哪:镜像拉取与容器编排的完整链路
OpenClaw 是一个面向 AI 编程助手的开源网关项目,能帮你把 Claude Code、Codex、Gemini CLI 这类命令行工具统一接到一个 API 通道上。它本身不绑定任何模型供应商,你给它一个 Base URL 和 Key,它就能把请求转发出去。适合谁?适合那些手头有好几个 AI 编程工具、每次换供应商都要改一遍环境变量、被各种 ANTHROPIC_BASE_URL 和 OPENAI_API_KEY 搞晕的人。
Docker 手工部署 OpenClaw 这件事,说难不难,说简单也容易踩坑。我见过太多人卡在第一步镜像拉取上,或者容器起来了但端口映射写错,浏览器死活打不开。更常见的是容器日志里报local proxy failed或者401 Unauthorized,然后就开始怀疑人生。
这篇内容聚焦的是完整的手工部署链路:从docker pull开始,到docker run或docker compose编排,再到端口映射、环境变量注入、启动报错排查,最后演示怎么通过 TaoToken 的统一 Key 和 API 通道完成模型接入。目标很明确——让你一次性跑通,不用反复试错。
整个流程我会拆成可复制的配置片段和逐步验证动作。你不需要提前理解 OpenClaw 的内部架构,跟着命令走就行。遇到报错也别慌,第五节我把高频错误和对应解法都列出来了。
先说清楚一个前提:OpenClaw 的 Docker 镜像托管在公开仓库,拉取不需要任何特殊网络配置。如果你所在的环境访问 Docker Hub 速度慢,可以配置国内镜像加速器,这是常规操作,跟部署本身无关。
部署完成后的架构是这样的:OpenClaw 容器监听一个本地端口(默认 3000),你在 Claude Code 或 Codex 里把 Base URL 指向http://localhost:3000,请求先到 OpenClaw,再由它根据你配置的供应商信息转发到真正的模型 API。TaoToken 在这里扮演的是统一 API 通道的角色,你只需要在 OpenClaw 里填一个 TaoToken 的 Key,后面换模型、换供应商都不用再动 Claude Code 的配置。
这个设计的好处是解耦。你的编程工具只认 OpenClaw 的地址,OpenClaw 认 TaoToken 的 Key,TaoToken 再去对接具体的模型。任何一层变了,其他层不用动。对于经常切换模型做对比测试的人来说,省下来的时间很可观。
接下来从环境准备开始,一步步走完整个部署流程。每个步骤都有对应的验证命令,确保你知道当前状态是否正常。
2. TaoToken 前置准备:统一 Key 与 API 通道的获取和配置
在开始 Docker 部署之前,先把 TaoToken 的 Key 拿到手。这一步很快,但顺序不能反——因为 OpenClaw 启动时需要读取环境变量里的 API Key,如果你先启动容器再补 Key,就得重启容器,多一步操作。
打开 TaoToken 官网,注册或登录后进入控制台。在 API Keys 页面创建一个新的 Key,复制保存。这个 Key 的格式通常是一串以sk-开头的字符串。注意,Key 只在创建时完整显示一次,关掉页面就看不到了,所以先粘贴到安全的地方。
TaoToken 的 API 端点地址是https://taotoken.net/api。这个地址在 OpenClaw 的配置里会用到,作为上游供应商的 Base URL。你不需要在 TaoToken 控制台里预先配置任何模型映射,OpenClaw 会把模型名称透传过去,TaoToken 根据模型名路由到对应的后端。
如果你打算用 Claude Code 作为客户端,还需要知道 TaoToken 对 Anthropic 格式接口的兼容路径。在 OpenClaw 的供应商配置里,Base URL 填https://taotoken.net/api,Key 填你刚创建的那个。OpenClaw 会自动处理 Anthropic 和 OpenAI 两种格式的转换。
这里有一个容易混淆的点:TaoToken 的 API 地址和官网地址不是同一个。官网是https://taotoken.net,API 是https://taotoken.net/api。配置的时候别填错,否则会返回 404 或者 HTML 页面而不是 JSON 响应。
拿到 Key 之后,建议先用 curl 验证一下 Key 是否有效。命令如下:
curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的Key" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 10 }'如果返回的 JSON 里有choices字段,说明 Key 和通道都正常。如果返回 401,检查 Key 是否复制完整;如果返回 404,检查 URL 是否写成了https://taotoken.net/api/v1/chat/completions而不是漏掉/api。
这一步验证通过后,再进入 Docker 部署环节。顺序很重要:先确认 Key 能用,再把它注入容器。否则容器启动失败时,你分不清是 Key 的问题还是 Docker 配置的问题。
另外提一句,TaoToken 的 Coding Plan 适合长期编码场景,如果你打算把 OpenClaw 作为日常开发的基础设施,可以了解一下。模型对话入口则适合快速验证某个模型是否可用,不用写代码就能测试。
3. 可复制配置:docker run 与 docker compose 两种编排方式
OpenClaw 的 Docker 部署有两种方式:单条docker run命令适合快速验证,docker compose适合长期运行和版本管理。两种方式我都给出完整配置,你按需选择。
先看docker run方式。这条命令包含了端口映射、环境变量注入和重启策略:
docker run -d \ --name openclaw \ --restart unless-stopped \ -p 3000:3000 \ -e TAOTOKEN_API_KEY="sk-你的Key" \ -e TAOTOKEN_BASE_URL="https://taotoken.net/api" \ -e DEFAULT_MODEL="claude-sonnet-4-20250514" \ -v openclaw-data:/app/data \ openclaw/openclaw:latest逐段解释。-d是后台运行,--name openclaw给容器起个名字方便管理。--restart unless-stopped让容器在意外退出时自动重启,除非你手动停了它。-p 3000:3000把容器内的 3000 端口映射到宿主机的 3000 端口,左边是宿主机,右边是容器,别写反。
环境变量部分,TAOTOKEN_API_KEY填你刚才创建的 Key,TAOTOKEN_BASE_URL填https://taotoken.net/api。DEFAULT_MODEL是默认模型 ID,当客户端没有指定模型时使用。-v openclaw-data:/app/data挂载一个数据卷,这样容器重建时配置不会丢。
如果你更喜欢docker compose,创建一个docker-compose.yml文件:
version: "3.9" services: openclaw: image: openclaw/openclaw:latest container_name: openclaw restart: unless-stopped ports: - "3000:3000" environment: - TAOTOKEN_API_KEY=sk-你的Key - TAOTOKEN_BASE_URL=https://taotoken.net/api - DEFAULT_MODEL=claude-sonnet-4-20250514 - LOG_LEVEL=info volumes: - openclaw-data:/app/data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 volumes: openclaw-data:这个 compose 文件比docker run多了健康检查配置。healthcheck每 30 秒请求一次/health端点,连续失败 3 次就标记容器不健康。配合restart: unless-stopped,容器不健康时 Docker 会自动重启它。
启动命令:
docker compose up -d查看日志:
docker compose logs -f openclaw如果你需要更精细的供应商配置,比如同时接入多个模型供应商,可以在宿主机创建一个config.json挂载到容器里。OpenClaw 支持从/app/data/config.json读取供应商列表:
{ "providers": [ { "name": "taotoken", "base_url": "https://taotoken.net/api", "api_key": "sk-你的Key", "models": [ "claude-sonnet-4-20250514", "gpt-4o", "gemini-2.5-pro" ] } ], "default_provider": "taotoken" }挂载方式是在docker run里加-v $(pwd)/config.json:/app/data/config.json,或者在 compose 的volumes里加一行- ./config.json:/app/data/config.json。
注意,如果你用了 config.json,环境变量里的TAOTOKEN_API_KEY可以省略,但TAOTOKEN_BASE_URL建议保留作为兜底。两种配置方式同时存在时,config.json 优先级更高。
配置写完后,先别急着启动。用docker compose config检查一下 YAML 语法是否正确,这个命令会输出解析后的完整配置,如果有语法错误会直接报出来。
4. 验证请求与成功结果:从容器健康检查到 Claude Code 接入
容器启动后,第一步是确认它真的在运行,而不是启动后立刻退出了。执行:
docker ps --filter name=openclaw如果看到状态是Up并且端口映射显示0.0.0.0:3000->3000/tcp,说明容器正常运行。如果状态是Exited,用docker logs openclaw看退出原因,常见的是环境变量缺失或端口被占用。
接下来验证 OpenClaw 的 HTTP 服务是否响应:
curl http://localhost:3000/health正常返回应该是{"status":"ok"}或类似的 JSON。如果返回Connection refused,说明容器虽然运行了但服务没起来,检查日志里有没有listening on port之类的信息。
再验证模型转发是否正常。用 OpenClaw 的/v1/chat/completions端点发一个测试请求:
curl -X POST http://localhost:3000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "说一句你好"}], "max_tokens": 50 }'如果返回的 JSON 里有choices[0].message.content并且内容是中文问候,说明 OpenClaw 已经成功把请求转发到 TaoToken 并拿到了模型响应。这一步是整个链路的关键验证点。
现在接入 Claude Code。在终端里设置环境变量:
export ANTHROPIC_BASE_URL="http://localhost:3000" export ANTHROPIC_AUTH_TOKEN="sk-你的Key"然后运行claude命令。如果 Claude Code 能正常启动并响应你的提问,说明整条链路打通了:Claude Code → OpenClaw → TaoToken → 模型。
如果你用的是 Codex,配置方式类似,但环境变量名不同。Codex 读取~/.codex/auth.json文件,内容格式如下:
{ "openai_api_key": "sk-你的Key", "api_base": "http://localhost:3000/v1" }注意 Codex 的api_base需要带/v1后缀,而 Claude Code 的ANTHROPIC_BASE_URL不带。这是两个工具的设计差异,配置时别搞混。
验证 Codex 是否接入成功:
codex "写一个 Python 的 hello world"如果 Codex 能正常输出代码,说明 OpenClaw 对 OpenAI 格式的兼容也没问题。
到这里,手工部署的核心链路已经跑通了。容器在跑,健康检查通过,模型转发正常,Claude Code 和 Codex 都能接入。接下来处理可能遇到的报错。
5. 本篇常见错误排查:401、local proxy failed 与 reading choices 报错
部署过程中最常见的报错有四个,我按出现频率排序,逐个给出排查步骤。
错误一:401 Unauthorized
现象是 curl 请求返回{"error":{"message":"Invalid API key","type":"authentication_error"}}。原因通常是 Key 复制不完整、Key 已过期、或者环境变量名写错了。
排查步骤:先确认TAOTOKEN_API_KEY的值是否以sk-开头且没有多余空格。然后检查 OpenClaw 日志里打印的 Key 前缀是否和你预期的一致。如果日志里显示key: sk-***但实际 Key 是sk-abc123,说明环境变量没注入成功。
一个容易忽略的点:docker run命令里-e参数的值如果包含特殊字符,需要用引号包裹。比如-e TAOTOKEN_API_KEY="sk-abc"是正确的,-e TAOTOKEN_API_KEY=sk-abc在某些 shell 下也能工作,但为了保险建议加引号。
错误二:local proxy failed
这个报错通常出现在 OpenClaw 日志里,完整信息可能是local proxy failed: dial tcp: lookup taotoken.net: no such host。原因是容器内的 DNS 解析失败,或者容器网络模式配置有问题。
排查步骤:进入容器内部测试网络连通性:
docker exec -it openclaw sh curl -v https://taotoken.net/api如果容器内 curl 也失败,说明是 Docker 的 DNS 配置问题。可以在docker run时加--dns 8.8.8.8参数,或者在 compose 文件里加dns: 8.8.8.8。
如果容器内 curl 成功但 OpenClaw 仍然报 local proxy failed,检查TAOTOKEN_BASE_URL是否写成了https://taotoken.net(漏掉/api)。OpenClaw 会把请求发到https://taotoken.net/v1/chat/completions,这个路径不存在,所以代理失败。
错误三:reading choices 报错
现象是 Claude Code 或 Codex 报Error: reading choices: unexpected end of JSON input。这个报错说明 OpenClaw 返回的响应不是合法的 JSON,通常是上游返回了 HTML 错误页面或者空响应。
排查步骤:先用 curl 直接请求 OpenClaw 的端点,看返回的原始内容是什么。如果返回的是 HTML,说明请求被重定向到了某个登录页或者错误页。检查TAOTOKEN_BASE_URL是否被错误地配置成了官网地址而不是 API 地址。
另一个可能的原因是模型 ID 写错了。比如你填了claude-sonnet-4但 TaoToken 实际支持的模型 ID 是claude-sonnet-4-20250514。模型不存在时,上游可能返回非 JSON 格式的错误信息。解决办法是查阅 TaoToken 的模型列表文档,确认模型 ID 拼写正确。
错误四:OAuth 相关报错
如果你在 Claude Code 里看到OAuth token expired或Please run claude login,说明 Claude Code 尝试用 OAuth 方式认证而不是用你设置的ANTHROPIC_AUTH_TOKEN。原因是 Claude Code 的配置优先级问题:如果之前登录过官方账号,OAuth token 会覆盖环境变量。
解决办法是清除 Claude Code 的本地认证缓存。在 Linux/macOS 上删除~/.claude/auth.json,在 Windows 上删除%APPDATA%\claude\auth.json。然后重新设置环境变量并启动。
如果问题依旧,检查是否有ANTHROPIC_API_KEY环境变量残留。Claude Code 会优先读取ANTHROPIC_API_KEY而不是ANTHROPIC_AUTH_TOKEN。用env | grep ANTHROPIC查看所有相关变量,把不需要的 unset 掉。
错误五:端口冲突
现象是容器启动后立刻退出,日志显示bind: address already in use。原因是宿主机的 3000 端口被其他程序占用了。用lsof -i :3000或netstat -tlnp | grep 3000找到占用进程,要么停掉它,要么把 OpenClaw 的端口映射改成-p 3001:3000。
排查完这些错误后,如果还有问题,可以对照 OpenClaw 的接入文档检查配置。文档里有完整的配置项说明和示例。
6. 长期编码场景的 CTA:用 Coding Plan 把 OpenClaw 变成日常基础设施
OpenClaw 跑通之后,你可能会想把它固定下来作为日常开发的基础设施。这时候有几个优化方向值得考虑。
第一是持久化配置。前面用的docker run方式在容器重建后环境变量会丢失,建议改用docker compose并把配置写在docker-compose.yml里,或者用.env文件管理敏感信息。.env文件的内容格式如下:
TAOTOKEN_API_KEY=sk-你的Key TAOTOKEN_BASE_URL=https://taotoken.net/api DEFAULT_MODEL=claude-sonnet-4-20250514然后在docker-compose.yml里用env_file: .env引用。这样 Key 不会出现在 compose 文件里,提交到 git 时也更安全。
第二是日志管理。OpenClaw 默认输出到 stdout,Docker 会接管这些日志。如果长期运行,日志文件会越来越大。可以在 compose 里配置日志轮转:
logging: driver: "json-file" options: max-size: "10m" max-file: "3"这样每个日志文件最大 10MB,最多保留 3 个,总共不超过 30MB。
第三是模型切换的灵活性。OpenClaw 支持在请求头里指定模型,你可以在 Claude Code 里通过/model命令切换模型,OpenClaw 会把模型名透传给 TaoToken。这意味着你不需要改任何配置就能在 Claude、GPT、Gemini 之间切换。
如果你打算把 OpenClaw 用于团队协作,可以考虑把配置文件和 Docker 镜像推送到内部仓库,新成员只需要docker compose up -d就能获得一致的开发环境。
对于长期编码场景,TaoToken 的 Coding Plan 提供了更稳定的通道和更高的速率限制。如果你每天有大量代码生成和调试需求,可以了解一下。模型对话入口适合快速测试新模型是否满足你的需求,不用改任何配置就能对比不同模型的输出质量。
最后提醒一点:OpenClaw 的版本更新比较频繁,建议定期执行docker compose pull拉取最新镜像,然后docker compose up -d重建容器。数据卷openclaw-data会保留你的配置,不用担心丢失。
整个部署流程到这里就完整了。从镜像拉取到容器编排,从端口映射到模型接入,再到报错排查,每一步都有对应的命令和验证方法。你按这个流程走一遍,应该能顺利跑通。遇到问题先看日志,大部分错误在日志里都有明确提示。