OpenClaw这套东西,我一开始是在裸机上硬装的,折腾完Node版本、Python依赖、各种模型SDK之后,系统已经乱得不像样。后来彻底换思路,用Docker把OpenClaw跑起来,连同10个实用的skills一起配好,整个过程不到40分钟。这篇就把这40分钟里的关键动作和后面几个月的实测经验一次性写清楚:Docker环境怎么准备、OpenClaw容器怎么起、10个skills具体怎么配、以及最常踩的几个报错怎么修。适合刚接触OpenClaw、打算把它当主力Agent框架用的朋友,也适合那种本机已经装过、但受不了环境越搞越乱的折腾党。
1. 为什么是Docker:OpenClaw这种Agent框架的部署逻辑
1.1 裸机部署OpenClaw的痛,你应该也经历过
OpenClaw本质上是一个带skill扩展机制的Agent运行时,思路和Claude Code、Codex这类工具接近,但更强调把微信、飞书这类消息入口,和本地或云端的各种模型统一收口到一个服务里。听起来很美好,可真在裸机上部署时,问题就来了:它要调用不同模型厂商的SDK,有些SDK依赖特定版本的Python,有些又要特定版本的Node运行时;你为了一个功能升级了依赖,结果另一个模块直接起不来。最常见的表现是——你今天还能跑通的对话,明天更新完某个包,全部接口开始报奇怪的SSL错误或JSON解析失败。
我第一回装的时候,光是把环境变量配齐就花了一个下午。OpenClaw自身有配置文件,模型厂商的API Key要配,日志目录要配,skill目录要配,还有一堆可选组件的开关。这些配置在裸机上散落在不同位置,一旦你要换机器或者重装系统,等于全部重来一遍。
用Docker之后,这些事被收敛成了一个镜像加一个挂载目录。镜像把运行时、依赖、启动脚本全部固化进去,宿主机上只需要留一份配置和一份skill挂载目录。换机器时,把这两个目录带走,重新docker compose up -d,服务就回来了。
1.2 容器化部署的价值不只是省事
很多人以为Docker部署只是"图省事",其实对OpenClaw这种Agent框架来说,容器化还有三个更实际的好处:
- 隔离模型SDK的依赖冲突。OpenClaw要同时对接云端API和本地模型,这两类依赖经常互踩。放进容器后,互踩的问题只在镜像构建阶段出现一次,运行期不再受影响。
- 数据持久化非常清晰。OpenClaw的会话记录、skill配置、密钥信息,裸机部署时分散在多个隐藏目录。容器方案通过一个数据卷集中管理,备份和迁移都方便。
- 版本回滚成本极低。镜像tag一换,docker compose up -d就完成升级或回滚,不用在宿主机上盲改一堆依赖。
接触过Kubernetes或者Compose的人应该熟悉这个模式:镜像管运行时,卷管数据,端口映射管对外暴露。OpenClaw部署也不例外。
我实际用的目录结构大致是这样的:
text复制openclaw/
├── docker-compose.yml
├── .env
├── data/ # 会话数据、配置
│ └── .openclaw/
└── skills/ # 所有skills挂载目录
├── write-novel/
├── article-draft/
└── ...
data目录挂到容器内的用户目录,skills目录挂到容器内的skills根目录。这样宿主机的编辑器和容器的运行时共用同一份文件,改完skill重启容器就生效,非常顺手。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 部署前夜:Docker Desktop安装与虚拟化爆雷排查
2.1 启动失败的经典报错:virtualisation support wasn't detected
很多人装完Docker Desktop,一点启动图标,直接看到"Failed to start because virtualisation support wasn't detected"之类的提示。这个报错本身其实已经说明了问题——Docker Desktop依赖Windows的虚拟化能力,而你的机器没有把它打开。但"怎么打开"才是真正的坑,因为这里牵扯到BIOS、Windows功能、WSL2三层的设置。
我当时排查的顺序是这样的:
第一,确认Windows系统本身的虚拟化是否可用。打开任务管理器,切到"性能"标签,看CPU那一栏右下角有没有"虚拟化:已启用"。如果显示"已禁用",就需要重启进BIOS,在CPU设置里打开Intel VT-x或AMD-V。这一步跨品牌的主板位置不一样,有些在Advanced里,有些在Security里,关键词搜VT-x、Virtualization Technology就行。
第二,如果任务管理器显示虚拟化已启用,但Docker Desktop还是报同样的错,那就得看Windows功能开关。在"启用或关闭Windows功能"里,勾选"Hyper-V"和"适用于Linux的Windows子系统"两项,然后重启。注意Hyper-V和某些第三方虚拟机软件(比如老版本VMware)会冲突,如果你机器上装过其他虚拟化软件,最好先确认它们的兼容性。
第三,WSL2是Docker Desktop在Windows上运行的核心依赖。打开PowerShell执行:
powershell复制wsl --set-default-version 2
如果提示内核版本太旧,去官方文档更新一下WSL2内核包。之后再执行wsl -l -v确认发行版状态,状态应该是2而不是1。
排查完之后,按这个顺序重启一次:BIOS设置保存 → 进系统开Windows功能 → 重启 → 启动Docker Desktop。我见过不少人是BIOS没开虚拟化就直接装Docker Desktop,结果所有设置全做完还是不启动,最后发现是第一步漏了。
2.2 镜像下载慢,先别急着找代理
Docker跑起来之后,马上会遇到另一个痛点:拉镜像慢到怀疑人生。OpenClaw的镜像通常比较大,因为里面除了基础运行时还可能带了不少依赖,卡在几百兆的下载进度条上是常有的事。
这里我会先做一个简单判断:如果网络环境正常,最有效的方案是配置镜像加速器。Docker Desktop的设置里有一个Docker Engine的JSON配置,在里面加上registry-mirrors即可。不同地区的加速地址不一样,我也没法给一个"永远有效"的地址,但通常社区里能搜到的国内加速源都可以试,配置完要点Apply & Restart。
注意一个细节:加速器只对Docker Hub的官方镜像生效。如果你用的是其他registry(比如GitHub Container Registry),加速器帮不上忙,这种情况就只能靠网络质量,或者考虑分时段拉取、用代理的方式。我没有在这里推荐任何代理工具,你自己按实际网络情况处理。
2.3 Mac用户的环境差异
如果你用的是Mac,尤其Apple Silicon芯片的Mac mini或MacBook,Docker Desktop本身的安装比Windows顺利得多,但有两个点要留意。
第一,Apple Silicon默认的镜像平台是arm64,而有一些依赖老代码的镜像只有x86_64版本。拉下来能跑,但性能会因为转译打折扣,有些极端情况下会直接崩溃。解决方案是找多架构镜像,或者在docker-compose.yml里显式指定platform: linux/amd64,让Docker用Rosetta转译。我个人的建议是优先用arm64镜像,省电也省内存。
第二,Mac的内存分配。OpenClaw如果同时要跑本地模型和容器服务,内存压力会很大。Docker Desktop默认的虚拟机内存只有2GB,建议在设置里调到8GB以上。这不算OpenClaw的坑,但很多"OpenClaw跑着跑着就无响应"的问题,其实都是Docker虚拟机内存爆了。
3. 30分钟跑起OpenClaw:Compose配置、模型接入与Control UI
3.1 最小可用的docker-compose.yml
OpenClaw官方仓库给出了不同部署方式的模板,我整理了一份最小可用的Compose配置。这个配置适合单机使用,把数据卷、端口和环境变量都分开管理:
yaml复制services:
openclaw:
image: ghcr.io/openclaw/openclaw:latest
container_name: openclaw
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- ./data:/root/.openclaw
- ./skills:/app/skills
env_file:
- .env
对应的.env文件:
env复制OPENCLAW_MODEL=deepseek-chat
OPENCLAW_API_KEY=你的密钥
OPENCLAW_CONTROL_UI=true
启动就两条命令:
bash复制docker compose up -d
docker compose logs -f
看到日志里出现类似"listening on 0.0.0.0:3000"的提示,就说明核心服务起来了。浏览器打开http://localhost:3000,应该能看到Control UI的控制台界面。
这个配置的精髓在于:镜像版本用latest还是固定tag,取决于你对稳定的要求。生产环境我建议锁定一个具体版本号,避免哪天官方推送新镜像后行为变化。在自己折腾阶段,用latest也挺好,docker compose pull && docker compose up -d一句命令就能尝鲜。
3.2 模型接入:从DeepSeek到NVIDIA NIM
OpenClaw本身不生产模型,它只是模型的调用方。配置模型时,我踩过最大的坑是"模型名不对"。最常见的报错是:
text复制agent failed before reply: unknown model: deepseek
这种报错十有八九是配置文件里写的模型名和模型服务商实际返回的模型ID对不上。以DeepSeek为例,在OpenAI兼容接口里,模型ID通常要写成完整的标识符,不同时期它家API的命名可能还不一样。很多教程只会告诉你"配置deepseek模型",却不说清楚模型ID要写具体版本,于是你写了deepseek,服务端不认,直接给你unknown model。
处理方式很简单:去对应模型平台的API文档里查当前可用的模型ID,填到.env的OPENCLAW_MODEL里,改完重启容器。别凭印象写。
除了云端API,OpenClaw也支持通过OpenAI兼容协议接本地模型服务。2024年底到2025年初,很多人开始用NVIDIA NIM搭建本地推理端点,OpenClaw里配置NIM的base_url和模型名即可。NIM的好处是它做了推理优化,在单张消费级显卡上也能跑出不错的效果;缺点是要自己搞定GPU驱动和显存规划。如果你用Mac mini这类没有NVIDIA GPU的设备,更现实的做法是用Ollama或llama.cpp起一个OpenAI兼容端点,OpenClaw里指向这个端点,一样能跑本地模型。
3.3 服务验证的几条命令
服务到底起没起好,不要只看"容器状态是Up"就完事。我习惯做三步验证:
bash复制# 1. 看容器实时日志,确认没有循环报错
docker compose logs --tail=50 openclaw
# 2. 检查端口监听
curl http://localhost:3000/api/health
# 3. 如果curl通,再提交一行对话测试
Control UI没起来的话,第2步就过不去。这个问题的排查我放在后面专门说。
如果你只是要验证模型配置对不对,可以在Control UI里发一条消息试试,或者用测试接口直接调用一次。注意第一次调用的响应时间可能比较长,因为模型服务商冷启动要几秒钟,别一看转圈就觉得挂了。
4. 先搞懂OpenClaw的skill机制:目录结构、YAML定义与安装方式
4.1 skill到底是什么
OpenClaw的skill机制,本质上是一套"提示词+工具声明"的标准化包装。一个skill就是告诉Agent:在什么情况下用我,用我的时候需要往上下文里塞什么内容,你自己要按什么规则输出。
它不是插件,不承载复杂逻辑,更不是一段被Agent执行的代码。这个定位很多人会搞混。你写skill时,不要把具体的Python脚本或Node逻辑塞进去,而是把"任务定义、输入输出格式、规则约束"写清楚。真正的执行能力,来自Agent自己调用底层工具。
这个机制设计得聪明的地方在于:它把"模型能力"和"业务需求"解耦了。底层换了更强大的模型,已经写好的skill不需要动,只要它的prompt写得足够通用,新模型自然能表现更好。
4.2 skill的目录结构和YAML定义
社区主流的skill结构,和我实际在OpenClaw里用的结构很接近:
text复制skills/
└── write-novel/
├── SKILL.md
└── assets/
└── example.json
SKILL.md是核心,用YAML frontmatter加上正文prompt组成。一个典型示例:
yaml复制---
name: write-novel
description: 当用户要求创作或续写小说章节时使用,支持根据大纲、人物设定和前情提要进行叙事写作
version: 1.0.0
---
你是一位资深网络文学编辑,擅长节奏控制和人物塑造。
用户会提供章节大纲、人物设定和前情提要。
你的任务:
1. 用一个吸引人的冲突或悬念开场,前200字内就要抓住读者
2. 对话要符合人物性格,避免书面腔
3. 每章控制在3000-5000字
4. 结尾留钩子
关键字段有三个:
- name:skill的唯一标识,调用时靠它定位
- description:Agent判断要不要使用这个skill的依据,写得越具体越好,最好包含典型触发场景
- 正文prompt:真正指导模型行为的部分
description的写法非常影响skill的命中率。写得太泛,Agent会乱用;写得太窄,该触发时不触发。一个好的description是"当出现X情况时使用,解决Y问题,输出Z格式"。
4.3 三种安装方式
我接触到的OpenClaw skill安装方式大概有三种,你可以按场景选:
- 手工安装:自己写SKILL.md,放到skills挂载目录。适合完全定制化的需求。
- 社区仓库克隆:GitHub上有很多现成的skills集合,比如人气很高的superpower-skills仓库,直接
git clone之后把需要的目录复制到skills目录。适合想快速积攒一批高质量skills、但不想自己写prompt的人。 - 通过Agent对话自动创建:有些版本支持在Control UI里直接让Agent帮你创建skill,它会把要求整理成规范文件放进skills目录。适合先跑通工作流、后期再手调的场景。
不管是哪种方式,装完都要记得重启容器。很多"我明明放了skill进去,Agent却根本不理"的情况,十有八九是容器里的skills目录没刷新。
4.4 写skill的三个原则
我写了十几个skill之后,总结出三个原则:
第一,单一职责。一个skill只做好一件事。写小说归写小说,写公众号文章归写公众号文章,不要做一个"全能写作助手",否则Agent的意图判断会变得很纠结。
第二,description要写触发场景,不要写能力描述。与其写"擅长各种写作任务",不如写"当用户提到要写小说、续写故事、构建世界观时使用"。第一种描述会让Agent很难判断什么时候该调用,第二种则清晰得多。
第三,prompt里要留足上下文接口。让用户给你的skill传什么,在prompt里明确列出。比如写小说需要"章节大纲、人物设定、前情提要"三件套,你就在prompt里写明"用户应当提供以下信息,如果缺失,先提问补齐再开始写作"。这样能减少模型放飞自我的概率。
5. 10个skills全清单:按场景挑选与验证结果
这部分是标题里的重头戏。我把实际装进OpenClaw的10个skills按场景分成三组,每一组你都可以直接抄配置。我不会把所有SKILL.md从头到尾贴一遍,但关键字段和设计思路都会说明白。
5.1 内容生产向:写小说、公众号文章、短视频脚本、文案润色、翻译本地化
这五个是我日常用得最勤的,也是OpenClaw这类Agent最容易体现价值的地方。
write-novel(写小说)。这个skill我一开始只想让它"续写章节",但发现如果不在prompt里约束风格一致性,模型很容易把人物写出性格分裂。后来我在SKILL.md里加了一个assets/example.json,存了一段"风格基准样本",prompt里明确要求"参考样本的语言风格和叙事节奏"。改完之后续写质量明显稳定了。
article-draft(公众号/博客文章)。这个skill的亮点是它兼顾了"内容生成"和"排版结构"。我整理的提示词会要求模型先输出大纲、再填充内容,而不是直接生成一坨全文。这样做的原因是:直接生成全文时,模型经常在中段跑偏,而先给大纲再逐步展开,至少能保证逻辑骨架是完整的。输出时我会要求它用Markdown格式,标题层级清晰,方便直接复制到编辑器发布。
short-video-script(短视频脚本)。短视频脚本的节奏和图文完全不一样,需要在头三秒抓住注意力,中间有反转或情绪高点,结尾引导互动。我写提示词时,把这三段结构直接写死,每一段的字数范围也给出来。这类任务不需要模型自由发挥太多,框架越明确,效果越稳定。
copy-polish(文案润色)。这个skill做得比通用润色更细:它区分了场景。给公众号改稿时,要求保留作者原有语气,只改冗余表达;给产品文案润色时,要求突出卖点、缩短句子。我在description里写了"当用户说润色、改稿、优化文案时使用",但场景识别还是靠正文prompt里的一串条件分支。
translate-localize(翻译与本地化)。这不是普通的翻译工具,而是专门处理"文化本地化"的skill。简单的英译中很多人都能用通用模型完成,但涉及到俚语、产品名、网络热词时,直译会非常生硬。这个skill会在prompt里强制模型先判断是否有需要本地化表达的片段,再给出意译方案,同时保留原文备查。对我平时翻译技术文档帮助很大。
5.2 开发效率向:前端页面开发、代码审查、Git提交信息
frontend-code(前端页面开发)。这个skill的定位不是"帮你会写代码",而是"按统一规范产出前端代码"。我在prompt里写清楚了UI组件库、样式方案、响应式断点、命名规则,这样模型每次生成的前端代码风格一致,不会这次用Tailwind下次用Bootstrap。它还会要求输出文件目录结构,方便我直接落地到项目里。
code-review(代码审查)。这个skill我给它的定位是"替补reviewer"。我会把一段diff或一个PR链接交给它,它按照安全性、性能、可维护性、边界条件四个维度输出评分和具体问题列表。prompt里我强调了一点:只指出确定的问题,不要干"建议用XX方式重构"这种主观性太强的废话。因为模型在代码评审时特别容易给出泛泛而谈的"优化建议",实际参考价值很低。
git-helper(Git提交信息与工作流)。它负责把一段杂乱的改动描述,整理成符合Conventional Commits规范的提交信息。这个skill看起来很小,但特别实用。很多Agent生成的提交信息要么天马行空,要么压根不符合规范,有了这个skill,提交记录变得干净很多。prompt里我还加了"如果检测到敏感信息(密钥、内部地址),要在提交前提醒"的规则。
5.3 效率协作向:会议纪要、邮件撰写
meeting-minutes(会议纪要)。每次开完会,把一长段语音转写文字扔给它,它能输出结构化的纪要:议题、结论、待办事项、责任人、截止时间。我在prompt里专门写了"如果原文中没有明确责任人和时间,不要编造,标注待确认"。这个约束很重要,因为模型在总结时倾向于"填空",没有的信息它会自己造一个合理值出来,这是很危险的。
email-compose(邮件撰写)。这个skill包含两种模式:正式邮件和同事间的轻松邮件。description里写的触发条件是"当用户要求写邮件、回复邮件时使用"。prompt里我会要求它在生成前先列出收件人身份和邮件目标,再决定语气和篇幅。实际体验下来,让模型"先说思路再写正文",比直接让它吐一封信要靠谱得多。
5.4 安装后的验证方式和效果
装完这10个skills后,我建议你别急着进入正式使用,先做一轮快速冒烟测试。方法是给Agent随便发几个不同类型的任务,比如"帮我写一段小说开头"、"帮我生成一篇活动通知的公众号初稿"、"总结一下这段语音转写的会议内容"。如果Agent没有调用对应的skill,而是直接凭通用能力回答,说明description写得不够清晰,或者skill目录没有被正确加载。
我实测下来的命中率大概在八成左右,剩下的两成主要是我用的模型对长description的语义理解不够准。换更强模型或者精简description之后,命中率会明显上升。
6. 打通消息链路:接入微信、飞书与本地模型Companion
6.1 把OpenClaw接进微信和飞书
OpenClaw真正的杀手锏,是它能把Agent接到日常消息软件里,让skill能力通过对话直接触达。我在部署后尝试了微信和飞书两条链路,体验差异很大。
微信接入要注意的点是:个人微信的接入方案通常依赖额外的协议适配层,容器部署时要把登录二维码通过端口映射或临时文件暴露出来。我第一次扫码登录时,二维码在容器日志里显示不全,折腾了半天才发现是终端宽度不够,把窗口拉大重新打印就好。另外,微信这种接入方式在Docker里跑时,要确保容器不会被意外重启导致登录态丢失,我会把data目录持久化,同时加上restart: unless-stopped。
飞书接入则正规得多。飞书开放平台支持自建应用,你只需要在飞书后台创建一个机器人应用,获取App ID和App Secret,然后把事件订阅的URL指向OpenClaw暴露出来的回调端口。这个流程没什么坑,唯一要注意的是飞书验证URL时要求你的服务能公网访问,这就需要你把3000端口或者单独的回调端口映射出去,并且保证HTTPS。很多人卡在"回调地址验证失败",基本都不是OpenClaw的问题,而是端口没通或者证书没配好。
6.2 本地模型Companion的配置思路
我一开始接的是云端API,速度快、效果稳,但总有一个担忧:如果某天网络波动,Agent的整个链路就断了。后来我在另一台有显卡的机器上搭了本地推理端点,把OpenClaw的模型配置切了过去。
这里我建议Companion本地模型用两步走:
第一步,先用单条消息验证本地端点的OpenAI兼容接口是否正常返回,办法是用curl直接POST一个对话补全请求,确认模型ID、认证方式都没问题。
第二步,再把OpenClaw的.env里相关配置指向这个本地端点,重启容器,发一条中文测试消息。
用Mac mini部署时,我踩过一个性能坑:默认的推理参数如果写得太高,Apple Silicon芯片跑量化模型时会产生明显发热和功耗上升。建议把最大token数调低一些,同时确认模型量化的版本适合你的内存大小。16GB内存的机器跑7B量化模型会很吃力,有条件就上大内存版本。
7. 踩坑实录:Control UI启动失败、unknown model与其他常见问题
7.1 Control UI did not start,怎么排查
这个报错我在Windows和Mac上都遇到过。现象是容器起来了,日志里也显示核心服务在跑,但浏览器访问3000端口始终打不开页面。
我的排查链路是这样的:先docker compose logs看有没有前端资源加载失败的记录,没有的话,再curl一下3000端口看返回什么。如果curl完全没响应,说明端口映射或监听地址有问题,检查compose里ports配置是否写了"0.0.0.0:3000:3000"。如果curl有响应但页面空白,多半是Control UI的前端构建文件和容器内的服务端版本不匹配,这时最简单有效的操作是docker compose pull重新拉取最新镜像,彻底重启。
有一次我折腾了很久,最后发现是浏览器缓存了旧页面。换无痕窗口打开就好了。这种低级错误说出来丢人,但确实常见,建议你排查时先排除这一条。
7.2 unknown model报错的完整处理
前文提到过这个报错。它本质上就是模型ID不匹配。我整理了一个判断顺序:
- 检查.env里的OPENCLAW_MODEL,确认写的是服务商API文档里的确切模型ID。
- 检查模型服务商账号是否有权限访问这个模型,有些新模型的权限需要单独申请。
- 如果配置的是本地NIM或Ollama端点,确认base_url指向的是完整可访问的地址,且模型名和本地拉取的模型标签一致。
做完这三步,九成问题能解决。剩下的一成是API Key本身无效或额度不足,这种报错信息通常不会是unknown model,而是401或403。
7.3 装完skill不生效的几个原因
装了skill,Agent却像没看见一样,这是我被问得最多的一个问题。每次我都会反问三个问题:
- 容器挂载的skills目录和你拷贝的目录,是不是同一个路径?我见过有人宿主机编辑的是./skills,compose里挂载的却是另一个目录,结果两拨文件互不相干。
- 装完之后有没有重启容器?skill目录是启动时加载的,热更新不是所有版本都支持。
- description写得够不够具体?如果description写得太笼统,模型会倾向于把它当普通上下文而不是"可调用能力"。
都排查完仍然不生效,那就直接在容器里看一眼目录到底有没有被挂载进去:
bash复制docker exec -it openclaw ls -R /app/skills
有时候宿主机上的目录和容器挂载关系因为路径写法的问题变成了"只挂载空目录",这一步可以一锤定音。
7.4 Docker层面容易踩的小坑
最后补几个和OpenClaw无关、但部署过程中一定会遇到的Docker通用问题。
- 端口被占用:3000端口如果被其他服务占了,compose起容器时会报端口冲突。改宿主机端口映射即可,比如"3001:3000"。
- 容器时间不对:有些镜像默认UTC时间,日志里的时间和本地对不上,排查问题时很困惑。在compose里加一行
environment: - TZ=Asia/Shanghai即可。 - 磁盘空间不足:Docker镜像和容器日志会悄悄吃满磁盘,尤其是长时间跑OpenClaw,日志文件增长很快。我通常给Docker配置一个日志轮转参数,限制单个容器日志大小。在docker-compose.yml里可以这样写:
yaml复制services:
openclaw:
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
这样日志最多占用150MB,不会无限膨胀。
最后再分享一个小技巧。我在写这10个skill的时候,第一个版本全都故意写得很"笨",每个skill只允许它做一件事,先把边界框住,跑通了再逐步扩展。原因很简单——你永远不知道一个提示词在真实模型上会脱缰到什么程度。有些skill看着逻辑完整,实际用起来模型就是不按套路走,与其一次追求大而全,不如先让它学会走,再慢慢学跑。这种"先笨后灵"的迭代方式,帮我省掉了大半的调试时间。
