
看到这个标题的时候我愣了一下这不就是我上周的真实写照吗用 Docker 部署 OpenClaw听起来就是一条docker compose up -d收工的事但我实际折腾下来前前后后花了整整两天才把容器跑稳、Control UI 打开、消息通道接上。OpenClaw 是个能接微信、飞书、自己写 skill 调外部 API 的多智能体个人助理官方也推荐用 Docker 跑但推荐归推荐坑一个都没少。这篇文章不聊官网教程里的标准操作只聊我在 docker 部署 OpenClaw 时真实踩过、以及在社区里看别人反复踩的坑从环境准备到 compose 配置再到容器起来之后的排查链路最后给一张可以直接照抄的自检清单。适合正准备折腾 OpenClaw 的 Docker 玩家也适合那种容器已经起了但 Control UI 一直打不开、Agent 半天不回话的老哥。1. 说句实在话Docker 部署 OpenClaw 前先搞清楚它要跑在什么环境里1.1 OpenClaw 是什么项目为什么大家首选 DockerOpenClaw 本质上是一个个人 AI 助理框架它把大模型对话、工具调用、skill 插件、多消息渠道整合在一起可以理解成能自己写技能、自己调 API、自己回复消息的智能体。它能接的渠道包括微信、飞书、Telegram 这类 IM 软件也能暴露一个 Control UI 让你在网页上管理对话和检查状态。为什么大家都推荐 Docker因为 OpenClaw 本身不是单个静态二进制文件它依赖模型 API SDK、消息网关适配器、可执行 skill 运行环境等一系列组件。直接在本机装Python 版本冲突、Node 版本不兼容、依赖库互相污染任何一个都能让你折腾一晚上。Docker 把这一坨依赖全部隔离在一个镜像里宿主机只需要装一个 Docker Engine理论上确实干净。但理论上三个字就注定了后面有故事。1.2 不同宿主机上的起始坑差别很大Docker 虽然跨平台但不同宿主机的跑法完全不是一回事我按平台把常见的坑先列一遍你可以直接对号入座Windows 用户需要 WSL2 作为后端Docker Desktop 对虚拟化支持的要求非常高。热搜里那句virtualization support not detected docker desktop failed to start because v就是这一类问题下面详细说。macOS 用户尤其 Apple SiliconM 系列芯片的 arm64 架构和 Linux amd64 架构并不完全一致如果镜像没有 arm64 版本或者 Docker Desktop 强行用模拟器跑 amd64 镜像性能会明显下降部分进程甚至直接段错误。热搜里mac mini 使用 docker 本地部署 openclaw大概率就是卡在这里。Linux 服务器用户相对最省心但要注意防火墙、SELinux/AppArmor 拦截、Docker 服务是否开机自启这几个点。还有内存分配OpenClaw 主进程加 Control UI再挂一个模型 API 并发2G 内存的机器跑起来会非常勉强。NAS 或软路由用户Docker 本身没问题但 NAS 的文件系统权限、内核版本、容器网络模式都可能拖后腿最容易出现容器起来了但 UI 打不开的诡异情况。我自己的实践结论是最低配置建议 2 核 4G日常能用但别开太多 skill想要流畅一点4 核 8G 起步。如果你还在同一个 Docker 环境里跑 Ollama 之类的本地模型那内存建议直接往 16G 以上走否则模型加载和 OpenClaw 常驻进程会互相抢内存表现就是容器频繁 OOM。2. Docker 环境层的坑拉不动镜像先别怪网络先看这三个地方2.1 Docker Desktop 虚拟化没开启动直接失败Windows 上装好 Docker Desktop第一次启动就弹窗提示virtualization support not detected。这个报错看起来像是 Docker Desktop 的问题实际上它只是汇报了问题真正的原因是你的机器没有正确开启硬件虚拟化。我建议按这个顺序排查打开任务管理器 - 性能 - CPU看右下角虚拟化是否显示已启用。如果是已禁用那就不是 Docker Desktop 的锅是 BIOS/UEFI 里的 VT-xIntel或 SVMAMD没开。重启进 BIOS把虚拟化技术、VT-d、Hyper-V 相关选项打开。注意不同主板厂商的名字不一样有的叫 Intel Virtualization Technology有的叫 Virtualization Extensions。回到 Windows 后确认启用了 WSL2 功能。可以在 PowerShell 里运行wsl --status查看如果版本不对或者没装内核手动更新 WSL2 内核包。最后再启动 Docker Desktop。这个坑和 OpenClaw 本身没关系但它是deployment 前的一道闸门很多人卡在 Docker Desktop 都起不来后面的一切都无从谈起。2.2 镜像架构和 tag 的隐藏坑docker compose up -d拉镜像是很常规的操作但 OpenClaw 这类新项目经常在镜像架构上翻车。例如 Apple Silicon 的 Mac mini 用户直接docker pull会按平台自动拉取对应架构镜像但有些镜像仓库并没有正确标注 arm64 版本Docker 会退而求其次拉 amd64 版本然后在你的机器上用模拟层运行。表现是什么镜像拉下来了容器也启动了但 CPU 占用奇高、Control UI 打开要十几秒甚至运行一段时间后容器闪退。这时候用docker inspect看镜像的Architecture字段就能发现是 amd64。解决方式有两种拉取时显式指定平台docker pull --platform linux/arm64 镜像名在 compose 文件里加platform: linux/arm64强制 Docker 使用 arm64 版本的镜像。另外tag 也要注意。不要无脑用latest。OpenClaw 更新频率不低latest可能昨天和今天的构建就有行为差异你照着旧教程配环境变量结果镜像换成新版本后变量名都不认了。建议锁定到你验证过的具体版本比如openclaw/openclaw:0.2.1等新版本功能确认稳定后再手动升级。2.3 仓库网络问题镜像加速器、重试和磁盘空间镜像拉不动是另一个高频问题但多数情况下不是 OpenClaw 的问题而是 Docker Hub 的连通性。常见表现是docker pull卡在 Waiting 或直接 EOF 超时。解决方案很成熟配置 Docker 镜像加速器也就是 registry mirror。以 Linux 为例在/etc/docker/daemon.json里加{ registry-mirrors: [https://你的加速器地址] }然后重启 Dockersudo systemctl daemon-reload sudo systemctl restart docker换个能用的加速器地址就行每家服务商给的具体地址不一样找自己云服务商文档里提供的即可。另外如果磁盘空间不够docker pull也可能报no space left on device这个隐藏得更深。建议先跑一下df -h看看磁盘余量再docker system df看 Docker 占了多少最直接的办法是docker system prune -a清理掉悬空镜像和构建缓存。3. compose 配置阶段的坑环境变量、模型名和目录挂载一个比一个隐蔽3.1 环境变量API Key 写错位置容器看起来运行了实际没起来容器层面的 Docker 环境问题解决后下一关就是 compose 配置。OpenClaw 的模型接入需要 API Key很多人习惯直接在docker-compose.yml里写死environment: - OPENCLAW_API_KEYsk-xxxx这种方式有两个问题。第一你的 Key 会出现在 shell 历史、git 提交记录、截图里第二如果 Key 里带有$符号compose 会尝试把它当成变量展开结果传进去的 Key 不完整启动日志显示认证失败你怎么看都看不出来。我建议的做法是把密钥放到.env文件里compose 中引用environment: - OPENCLAW_API_KEY${OPENCLAW_API_KEY}.env文件内容OPENCLAW_API_KEYsk-xxxx OPENCLAW_MODEL_PROVIDERdeepseek OPENCLAW_MODEL_NAMEdeepseek-chat这样不仅安全还能保证同样的 compose 文件在不同环境之间复用换一组 Key 不用改文件。3.2 模型报错 unknown model: deepseek 到底是什么原因热搜里那条openclaw zero token 安装后 agent failed before reply: unknown model: deepseek非常有代表性。这个错误看起来像是模型名写错了但更多人遇到的是配置里明明填了 deepseek为什么说不认识。这里的关键是 OpenClaw 把模型供应商和模型名是两个不同的配置维度。如果你填的是deepseek-chat但供应商配成了 OpenAI 兼容接口或者反过来供应商配成了 deepseek 但模型名填成了deepseek这个不存在的模型标识都会在启动时被模型网关拒绝最终表现为unknown model。解决方法是按官方文档里列出的模型对照表去填不要凭感觉写。比如 deepseek 的供应商标识、模型名称deepseek-chat、API 地址这三样要一致。你可以先在 Control UI 或者配置管理命令里把可用模型列表打出来确认你配置的模型名确实在这个列表里。3.3 目录挂载数据到底落在宿主机哪里重启会不会丢OpenClaw 的配置、会话记录、skill 数据都需要持久化。如果 compose 里只写了image和environment而没有volumes那么容器重启后一切回到初始状态你写入的配置全部丢失。更隐蔽的是你写了 volume 但宿主机目录权限不对容器内进程根本没权限写入启动时会报 Permission denied 或者静默失败。一个稳妥的挂载写法volumes: - ./openclaw_data:/app/data挂载之前先手动创建宿主机目录并给足权限mkdir -p ./openclaw_data chmod -R 777 ./openclaw_datachmod 777只是图省事生产环境不建议这么干可以根据镜像内用户的 UID 精确授权。但至少这一步能帮你排除权限不足这种低级问题。判断容器内用户 UID 可以用docker exec进容器执行id然后chown到对应 UID。3.4 compose 文件版本字段一个过时但普遍存在的报错点很多教程里依然会写version: 3但新版 Docker Compose 已经不再推荐使用version字段写了只会产生告警部分版本甚至会直接报解析错误。如果你使用的是docker composeV2 插件建议把version字段去掉。另外注意命令差异带横杠的docker-compose是 Python 旧版空格版的docker compose是插件版两者的配置解析在某些场景下行为略有不同我在排查时还遇到过同一个文件、两种命令执行结果不一样的情况。4. 容器起来以后Control UI 打不开、Agent 不回话排查链路要这样走4.1 Control UI 打不开先分清容器没起和端口没通热搜里有一条openclaw control ui did not start这个场景我太熟了。你docker compose up -d后看到容器状态是 Up以为一切正常但浏览器访问 Control UI 就是转圈或者直接拒绝连接。这时候不要急着改配置按这个链路排查先看容器状态docker compose ps。如果显示Exited (1)说明进程直接崩了去查日志。如果显示Up继续下一步。看 Control UI 进程是否真的在容器内监听docker exec -it 容器名 netstat -tlnp或ss -tlnp确认监听的是0.0.0.0还是127.0.0.1。如果只监听127.0.0.1你宿主机映射出去也没用因为容器内部的回环地址只有容器自己能访问。在宿主机上测试端口curl -I http://127.0.0.1:映射端口。如果宿主机能通但浏览器不通检查云服务商安全组和宿主机防火墙。如果端口不通看 compose 里的端口映射是不是写反了。8080:8080的含义是宿主机 8080 端口转发到容器 8080 端口写反成8080:9090而容器实际监听 9090那访问 8080 必然失败。还有一个隐藏点Control UI 组件可能受环境变量控制比如某些部署模式下默认禁用。你要确认镜像的默认配置里 Control UI 是开启的否则日志里根本没有 Control UI 启动记录。4.2 Agent 不回话不要只看界面要看 docker logsControl UI 能打开后你以为完事了结果发消息给 OpenClaw它半天不回复或者回一句出错了就没了。这时候界面上的错误信息非常有限真正的答案在日志里。打开日志docker compose logs -f openclaw常见错误分为几类认证失败日志里出现401 Unauthorized或invalid api key说明 Key 配置有问题去.env检查。模型不存在日志里出现unknown model或model not found按照 3.2 节说的模型对照表核对。网络超时日志里出现connection timeout、context deadline exceeded说明容器到模型 API 的网络有问题。如果你用的是国内模型服务且 API 在国内一般没问题但如果容器内 DNS 解析异常也会出现超时。上下文超长日志里出现maximum context length说明你输入的内容超出了模型窗口限制需要调整配置或减少单次对话内容。如果你怀疑是容器到模型 API 的网络问题可以进容器手动测一下连通性docker exec -it openclaw sh curl https://api.deepseek.com/v1/models这一步能快速区分是配置问题还是网络问题。4.3 容器内连宿主机本地模型localhost 指向的是容器自己很多人在宿主机上用 Ollama 跑本地模型然后 OpenClaw 里配置模型 API 地址写http://localhost:11434结果 Agent 一直提示连接失败。原因很简单容器内的localhost是容器自己不是宿主机OpenClaw 根本找不到宿主机的 Ollama。Docker 环境里访问宿主机服务要用特殊主机名host.docker.internal。OPENCLAW_MODEL_API_BASEhttp://host.docker.internal:11434/v1Docker Desktop 和 Docker Engine 20.10 以上版本通常都支持这个主机名。如果在 Linux 上host.docker.internal解析不了可以在 compose 里手动加上extra_hosts: - host.docker.internal:host-gateway这个配置会把host.docker.internal映射到宿主机的网关地址是 Linux 环境下的标准解法。我踩过一次这个坑后现在 compose 里都会无条件带上这一条。4.4 重启容器后配置丢失先检查 volume还有一种情况你配置好了模型、接入好了渠道运行正常结果docker compose down docker compose up -d之后所有配置回到初始状态。这基本可以断定是 volume 挂载没生效。检查一下:docker inspect openclaw | grep -A 5 Mounts如果Mounts部分为空说明 compose 里的volumes没有正确解析。常见原因是路径写错或者宿主机目录不存在时 Docker 自动创建了 root 所有的目录导致容器内写不进去。排查时看看宿主机当前目录下是否真的生成了挂载目录以及目录属主是否符合预期。5. 接入微信和飞书的坑内网回调、端口映射和权限绑定5.1 回调地址别填 localhost容器不知道宿主机在哪儿OpenClaw 支持接飞书、企业微信这类平台接入时平台要求填一个回调地址。很多人会想当然地填http://localhost:8080/callback然后怎么验证都过不了后台一直报回调失败。原因很简单这个回调地址是给飞书/企业微信的服务器访问的它是从公网发起请求的localhost在它的视角里指向飞书服务器自己跟你的容器没有任何关系。你需要填的是公网能访问到你宿主机的地址比如http://你的公网IP:映射端口/callback。如果你的宿主机没有公网 IP就得用内网穿透工具把本机端口暴露成一个公网可达的 HTTPS 地址。注意穿透工具的免费域名可能会被平台风控稳定方案是用自己的域名加反代。5.2 端口映射、监听地址和 HTTPS 回调就算你填了公网地址可能还是回调用失败。关键点在于容器内服务必须监听0.0.0.0而不是127.0.0.1。如果它只听本机回环宿主机的端口转发过去也不会被容器接收。宿主机防火墙和安全组必须放行对应端口。飞书、企业微信的回调要求 HTTPS只有 HTTP 的话平台直接拒绝连验签都不会走到。很多部署方案里大家习惯在容器里直接配 HTTPS 证书但这样每次换证书都麻烦。我更推荐用 Nginx 或 Caddy 在宿主机做一层反向代理容器内继续跑 HTTP反代层负责 HTTPS 终止和证书续期。这样 OpenClaw 容器不用关心证书问题回调地址指向反代域名即可。5.3 企业微信和飞书的验签逻辑、Token、EncodingAESKey接入企业微信应用时需要配置 Token、EncodingAESKey 和应用 Secret。这仨字段必须和你在管理后台填的完全一致任何一个字符不对验签就失败。容器里如果环境变量传递时带了多余的空格或引号也会造成验签失败而且日志里不会直接告诉你哪里不一致只会在回调日志里出现invalid signature。飞书那边类似回调 URL 里通常要带一个challenge参数首次配置时会做地址校验。如果 OpenClaw 容器在反代后面要确保反代把 URL 原样转发不要把 query string 吞掉。我踩过一个问题Nginx 反代默认会保留 query string但如果你写了proxy_pass http://127.0.0.1:8080/;这种带 URI 的写法有概率丢失原始请求参数。正确的做法是proxy_pass http://127.0.0.1:8080;不带路径。还有一个容易被忽略的点如果平台要求回调地址必须是 80/443 端口你的端口映射怎么写就很关键。比如容器监听 8080但是公网入口是 443你要在宿主机上做端口转发或者反代让 443 能到达容器的 8080。6. 排查排到怀疑人生后的自检清单照着抄能省一半时间6.1 症状、可能原因、排查命令对照表以下这张表是我部署和帮朋友排查时沉淀出来的按症状查原因效率比自己瞎试高得多症状可能原因排查命令解决方案Docker Desktop 启动失败硬件虚拟化未开启 / WSL2 未装任务管理器查看虚拟化状态wsl --status进 BIOS 开启 VT-x/AMD-V安装并更新 WSL2镜像拉取慢或失败网络问题 / 磁盘空间不足df -h、docker system df配置 registry mirrordocker system prune -a清理空间容器启动后立即退出配置错误 / 内存不足 / 端口冲突docker compose logs --tail 100查日志定位具体错误调整内存或端口Control UI 打不开端口映射错误 / 容器监听 127.0.0.1 / 安全组未放行curl -I http://127.0.0.1:端口、docker exec看监听地址修正映射让容器监听 0.0.0.0放行防火墙Agent 不回话API Key 无效 / 模型名错误 / 网络超时docker compose logs -f openclaw核对 Key、模型对照表、容器内 curl 测 API容器访问不了宿主机 Ollamalocalhost 指向容器自身docker exec openclaw curl http://host.docker.internal:11434用host.docker.internalLinux 加extra_hosts重启容器配置丢失volume 没挂上 / 挂载目录权限不足docker inspect 容器名 | grep -A 5 Mounts检查挂载路径和目录权限企业微信/飞书回调失败回调地址错误 / 无 HTTPS / 反代丢参数看 openclaw 日志检查反代配置填公网域名用 Nginx/Caddy 做 HTTPS 反向代理模型报 unknown model供应商和模型名不匹配Control UI 里查看可用模型列表按官方模型对照表配置别凭感觉填容器频繁被杀内存不足导致 OOMdocker stats查看内存占用增大宿主机内存或限制并发避免同时跑本地模型6.2 保持部署可复现compose 文件、.env.example 和备份最后说一个我自己总结的经验。部署 OpenClaw 这种多组件的容器化项目最怕的不是出错而是出错之后无法复现、无法回滚。现在我做任何事情之前都会维护一套基础的部署文件docker-compose.yml只放镜像、端口、volume、extra_hosts 这类结构信息不出现任何真实密钥。.env.example所有变量写成占位符提交到 git 或者发给同事对方只需要复制成.env并填上自己的 Key 就能跑。每次大升级之前先docker compose down然后把./openclaw_data整个目录打个压缩包备份再拉新镜像启动。如果新版本有问题直接恢复旧镜像和数据目录五分钟回滚。这些看似琐碎的习惯能在你折腾 OpenClaw 的时候省下大量时间。很多人的坑其实不是某个技术难点而是部署过程不可复制改了一个配置之后不知道哪一步导致的结果变化。我自己现在部署 OpenClaw固定做三件事所有密钥放进.env不进 composecompose 里无条件加上extra_hosts映射host.docker.internal每次升级前先备份数据目录再动镜像。这三件事帮我躲掉了后续 90% 的坑。如果你正准备用 Docker 跑 OpenClaw希望这篇能让你少踩几个我已经踩平了的坑。