1. 桌面与 Docker 双环境部署,OpenClaw 配置到底差在哪
OpenClaw 是一个支持多 Agent 协作、多渠道接入的本地优先 AI 网关框架,它能在桌面端开箱即用,也能通过 Docker 部署到服务器上做团队共享。适合谁?如果你是一个开发者,白天在 MacBook 上调试 Agent 逻辑,晚上想把同一套配置推到云服务器跑定时任务,那这篇就是写给你的。核心痛点其实不在安装,而在配置迁移:桌面模式默认把数据写进用户目录,Docker 模式则依赖挂载卷和环境变量,两边的config.toml与settings.json字段名一样、路径语义却不同,直接复制粘贴十有八九会报「config not found」或者「permission denied」。
我试过把桌面版的整个~/.openclaw目录打包丢进容器,结果 Gateway 起不来,日志里全是路径解析失败。后来才理清:桌面模式用相对路径 + 用户主目录展开,Docker 模式必须用绝对路径 + 卷映射。这篇会把两种模式的配置骨架都拆开,再给一套统一的 Key/API 通道接入方式,让你一次配置、两边平滑切换。整个流程分四步:先理解两种模式的目录差异,再准备 TaoToken 的 Key,然后分别写config.toml和settings.json,最后用一条 curl 验证请求打通。全程命令可复制,参数有说明,踩过的坑我会标出来。
2. 前置准备:TaoToken 统一 Key 与 API 通道
不管桌面还是 Docker,OpenClaw 都需要一个模型调用入口。TaoToken 提供统一的 API 通道,你只需要一个 Key,就能在两种环境里用同一套配置访问模型,不用为每个环境单独申请凭证。这一步做完,后面两套配置的base_url和api_key字段就能保持一致,迁移时只改路径、不改鉴权。
先到官网注册并进入控制台,地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,登录后左侧菜单找到 API Keys 页面:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。点「创建新 Key」,命名建议带上环境标识,比如openclaw-desktop和openclaw-docker,方便后续排查是哪个环境在调用。创建后立刻复制,页面刷新就不再完整显示。
拿到 Key 之后,API 的基础地址是https://taotoken.net/api,注意这个地址不带任何查询参数,直接作为base_url写入配置。如果你不确定模型名怎么写,可以打开模型对话页面手动发一条消息验证 Key 是否可用:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite 。在对话框里选一个模型,发「ping」,能收到回复说明 Key 和通道都正常。这一步别跳过,很多人后面配置报 401,其实是 Key 复制时带了空格。
注意:Key 属于敏感凭证,桌面环境建议放进系统钥匙串或
.env文件并加入.gitignore;Docker 环境用env_file或编排文件的环境变量注入,不要硬编码进镜像。
3. 可复制配置:config.toml 与 settings.json 双环境骨架
OpenClaw 的配置分两层:config.toml管 Gateway、端口、存储路径这些运行时参数;settings.json管模型通道、Agent 默认行为这些业务参数。桌面和 Docker 的差异集中在config.toml的路径与端口绑定,settings.json基本可以完全复用。
3.1 桌面模式 config.toml 骨架
桌面模式默认读取~/.openclaw/config.toml,路径可以用~展开,端口绑定127.0.0.1即可,避免暴露到局域网。
# ~/.openclaw/config.toml —— 桌面模式 [gateway] host = "127.0.0.1" port = 18789 control_port = 18790 [storage] data_dir = "~/.openclaw/data" plugins_dir = "~/.openclaw/plugins" session_db = "~/.openclaw/data/sessions.sqlite" [logging] level = "info" format = "text" [security] secret = "desktop-local-secret"关键点:data_dir和plugins_dir用~开头,OpenClaw 启动时会展开成用户主目录。session_db指向 SQLite 文件,桌面模式默认用 SQLite,不需要额外数据库服务。
3.2 Docker 模式 config.toml 骨架
Docker 模式必须用绝对路径,且路径要和docker-compose.yml里的卷映射一致。容器内的工作目录建议统一挂到/data和/config。
# /config/config.toml —— Docker 模式 [gateway] host = "0.0.0.0" port = 18789 control_port = 18790 [storage] data_dir = "/data" plugins_dir = "/plugins" session_db = "/data/sessions.sqlite" [logging] level = "info" format = "json" [security] secret = "${OPENCLAW_SECRET}"差异一目了然:host改成0.0.0.0让容器外能访问,路径全部绝对化,secret用环境变量占位符,由编排文件注入。format改成json是为了配合服务器上的日志收集。
3.3 settings.json 通用骨架
这个文件两种环境可以完全一样,放在~/.openclaw/settings.json(桌面)或/config/settings.json(Docker)。核心是把模型通道指向 TaoToken。
{ "models": { "default": "claude-sonnet", "providers": { "taotoken": { "base_url": "https://taotoken.net/api", "api_key": "${TAOTOKEN_API_KEY}", "models": ["claude-sonnet", "gpt-4o", "deepseek-chat"] } } }, "agents": { "default_model": "taotoken/claude-sonnet", "max_tokens": 4096, "temperature": 0.7 }, "channels": { "telegram": { "enabled": false }, "discord": { "enabled": false } } }api_key用${TAOTOKEN_API_KEY}占位,桌面模式通过.env或 shell 导出,Docker 模式通过environment注入。这样同一份settings.json在两个环境都能跑,迁移时不用改任何字段。
3.4 docker-compose.yml 编排骨架
把上面的 Docker 配置串起来,编排文件长这样:
version: '3.8' services: openclaw: image: openclaw/openclaw:latest container_name: openclaw restart: unless-stopped ports: - "18789:18789" - "18790:18790" volumes: - ./data:/data - ./config:/config - ./plugins:/plugins environment: - OPENCLAW_CONFIG=/config/config.toml - OPENCLAW_SECRET=${OPENCLAW_SECRET} - TAOTOKEN_API_KEY=${TAOTOKEN_API_KEY} networks: - openclaw-net networks: openclaw-net: driver: bridge启动前在同目录建一个.env文件,写入OPENCLAW_SECRET和TAOTOKEN_API_KEY两个变量,然后docker compose up -d。容器起来后docker logs openclaw应该能看到 Gateway 监听 18789 的日志。
4. 验证请求:一条 curl 打通两种环境
配置写完不算完,得实际发一条请求确认通道可用。桌面模式直接在终端跑,Docker 模式进容器跑或者从宿主机打端口都行。
curl -X POST http://127.0.0.1:18789/api/v1/chat \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${TAOTOKEN_API_KEY}" \ -d '{ "model": "taotoken/claude-sonnet", "messages": [{"role": "user", "content": "回复 pong"}], "max_tokens": 32 }'桌面模式预期返回类似:
{ "id": "chatcmpl-xxx", "object": "chat.completion", "model": "claude-sonnet", "choices": [{"message": {"role": "assistant", "content": "pong"}}] }Docker 模式如果从宿主机打,把127.0.0.1换成服务器 IP;如果进容器打,用http://localhost:18789。返回 200 且content里有内容,说明 Gateway、TaoToken 通道、Key 三者全部打通。这一步成功后,你可以把同一条 curl 存成healthcheck.sh,两种环境共用。
如果你更想先确认模型侧没问题,可以打开模型对话页面手动发一条:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite ,选同一个模型名,对比返回是否一致。两边都对,说明配置没有语义偏差。
5. 本篇常见错排查
报错一:config not found at /config/config.tomlDocker 模式最常见。检查docker-compose.yml里OPENCLAW_CONFIG的值和卷映射的目标路径是否一致。如果你把配置放在./config/config.toml,映射到容器/config,那环境变量就得写/config/config.toml,少一层目录都会找不到。
报错二:permission denied写 SQLite容器内进程默认以非 root 用户跑,宿主机挂载的./data目录如果属主是 root,容器写不进去。解决:chown -R 1000:1000 ./data ./config ./plugins,或者编排文件里加user: "1000:1000"。桌面模式一般不会遇到,因为文件属主就是你自己。
报错三:401 UnauthorizedKey 没传进去或者传错了。先确认.env文件里TAOTOKEN_API_KEY没有引号、没有换行;再确认settings.json里的占位符拼写和.env变量名完全一致,大小写敏感。Docker 模式可以用docker exec openclaw env | grep TAOTOKEN看变量是否注入成功。
报错四:端口 18789 被占用桌面模式如果之前起过 OpenClaw 没退干净,lsof -i :18789找到进程 kill 掉。Docker 模式检查宿主机有没有别的服务占了 18789,改映射端口比如"28789:18789",同时 curl 也要换成 28789。
报错五:模型名 404settings.json里models数组的模型名必须和 TaoToken 通道支持的名称一致。不确定就打开模型对话页面看下拉列表,或者用/api/v1/models接口拉一次列表。别自己拼taotoken/claude-sonnet之外的别名。
6. 迁移与长期编码:把配置骨架用起来
两种环境切换时,你只需要做三件事:把config.toml的路径段换成目标环境的版本,把.env或环境变量注入到目标环境,然后重启 Gateway。settings.json原样复制,不用动。这套骨架的意义就在于把「环境差异」收敛到config.toml一个文件里,业务配置保持单一来源。
如果你打算长期在服务器上跑 Agent 做编码任务或者定时工作流,建议把 Key 管理也统一起来。TaoToken 的 Coding Plan 适合这种持续调用的场景,配置方式不变,只是 Key 的额度策略不同:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。接入文档里有完整的字段说明和更多模型名列表,遇到配置字段不确定时直接查:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
最后留一个实用习惯:把config.toml和settings.json放进 Git 仓库,但.env永远不进。桌面和 Docker 各维护一个config.toml分支,合并时只同步settings.json。这样下次换机器或者扩容器,五分钟就能拉起来一套一模一样的环境。