
1. 为什么 OpenClaw 用 Docker 部署总踩坑环境隔离与依赖冲突的真实场景OpenClaw 是一个面向机器人控制与自动化任务的开源框架它能帮你把传感器数据采集、运动规划、任务调度这些模块串起来跑。适合谁做机器人原型验证的开发者、需要把算法快速落地到边缘设备的团队以及想在一台机器上同时跑多个版本做对比测试的人。问题在于OpenClaw 的依赖链相当长C 编译工具链、Eigen、yaml-cpp、Boost、OpenSSL再加 Python 虚拟环境和一堆 pip 包。你如果直接装在宿主机上大概率会遇到三种情况一是和系统自带的 Python 版本打架二是 Boost 版本和别的项目冲突三是升级一次系统就把编译好的二进制搞崩。我试过在一台 Ubuntu 上同时装 OpenClaw 和另一个视觉项目结果两个项目对 OpenCV 和 Boost 的版本要求不同折腾了一下午才把环境变量理清楚。后来换成 Docker 之后这类问题基本消失了——每个容器有自己的文件系统、自己的依赖树宿主机只负责提供内核和 Docker 运行时。这就是环境隔离的核心价值OpenClaw 跑在容器里它用什么版本的库、装了什么包都不会污染宿主机也不会被宿主机的其他项目影响。但 Docker 部署也不是复制粘贴就完事。很多人卡在几个地方镜像构建时依赖装不全导致编译失败、容器启动后端口不通、挂载目录权限不对导致配置文件读不到、设备节点映射不进去导致硬件访问失败。这篇教程就围绕 OpenClaw Docker 安装与部署的完整流程把 Dockerfile、compose 配置、目录挂载、启动验证、隔离效果检查这些环节拆开讲每一步都给可复制的命令和配置。你跟着做能在本地或服务器上把 OpenClaw 稳定跑起来并且清楚知道隔离边界在哪里。先明确一个前提Docker 解决的是运行环境隔离不是网络访问问题。如果你的服务器本身网络受限那是另一回事本文不涉及。我们聚焦在容器化部署本身包括镜像怎么构建、容器怎么跑、数据怎么持久化、多服务怎么编排。下面从环境准备开始一步步来。2. TaoToken 前置准备获取 API Key 与接入配置OpenClaw 本身是一个机器人控制框架但它在任务调度和决策环节可以接入大模型能力比如用自然语言描述任务、让模型生成动作序列。TaoToken 在这里的角色是提供统一的模型调用入口你不需要在容器里单独配置各家模型的 SDK只要拿到一个 API Key在 OpenClaw 的配置里填上 Base URL 和 Model ID 就行。这样容器内的 OpenClaw 通过标准接口调用模型和宿主机环境完全解耦。第一步是获取 API Key。打开 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册登录后进入控制台。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 在左侧菜单找到 API Keys 页面点击创建新的 Key。创建时给它起个名字比如 openclaw-docker方便后面区分。创建完成后立刻复制 Key页面刷新后就看不到了。这个 Key 就是后面配置里的TAOTOKEN_API_KEY。第二步是确认 Base URL 和 Model ID。TaoToken 的 API 端点是 https://taotoken.net/api 注意这个地址不带任何查询参数直接作为 Base URL 使用。Model ID 根据你要用的模型来填比如 claude-sonnet-4-20250514 或者 gpt-4o 这类。你可以在模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 先测试一下模型是否可用确认返回正常后再写进 OpenClaw 配置。第三步是理解接入方式。OpenClaw 容器内通过 HTTP 请求调用 TaoToken 的 API请求头里带Authorization: Bearer 你的Key请求体里指定 model 和 messages。因为容器有独立的网络命名空间它访问外网走的是宿主机的网络出口所以只要宿主机能访问 TaoToken 的 API 端点容器里就能访问。你不需要在容器里装任何额外的代理工具也不需要在 Docker 里做特殊网络配置。如果你打算长期跑编码类或 Agent 类任务可以了解一下 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 它针对持续调用场景做了额度优化。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有各语言的调用示例容器里用 curl 或 Python requests 都能直接跑。拿到 Key 之后先别急着写进 Dockerfile。正确的做法是通过环境变量注入而不是硬编码在镜像里。这样镜像可以复用Key 也不会泄露到镜像层。下面在 compose 配置里会具体写怎么注入。3. 可复制配置Dockerfile 与 docker-compose.yml 完整示例这一节给出完整的配置文件你直接复制到项目目录里就能用。先建一个工作目录比如~/openclaw-docker在里面创建Dockerfile、docker-compose.yml、config/openclaw.yaml和data/目录。先看 Dockerfile。这里基于 Ubuntu 22.04装好编译依赖克隆 OpenClaw 源码建虚拟环境编译安装。注意用非 root 用户运行减少权限风险。FROM ubuntu:22.04 ENV DEBIAN_FRONTENDnoninteractive ENV OPENCLAW_HOME/opt/openclaw ENV PATH$OPENCLAW_HOME/bin:$PATH RUN apt-get update apt-get install -y \ build-essential \ python3 \ python3-pip \ python3-venv \ python3-dev \ git \ cmake \ libeigen3-dev \ libyaml-cpp-dev \ libboost-all-dev \ libssl-dev \ curl \ rm -rf /var/lib/apt/lists/* RUN useradd -m -u 1000 openclaw RUN git clone https://github.com/openclaw/openclaw.git $OPENCLAW_HOME RUN chown -R openclaw:openclaw $OPENCLAW_HOME USER openclaw RUN python3 -m venv $OPENCLAW_HOME/venv RUN $OPENCLAW_HOME/venv/bin/pip install --upgrade pip \ $OPENCLAW_HOME/venv/bin/pip install -r $OPENCLAW_HOME/requirements.txt RUN mkdir -p $OPENCLAW_HOME/build \ cd $OPENCLAW_HOME/build \ cmake .. -DCMAKE_BUILD_TYPERelease \ make -j$(nproc) WORKDIR /workspace EXPOSE 8080 CMD [openclaw, start]构建镜像cd ~/openclaw-docker docker build -t openclaw/openclaw:custom .构建过程大概几分钟取决于网络和 CPU。如果卡在 pip install 或 cmake 阶段先检查网络是否能访问 GitHub 和 PyPI。构建完成后用docker images | grep openclaw确认镜像存在。接下来是 docker-compose.yml。这里把 OpenClaw 和 Redis、PostgreSQL 编排在一起Redis 做任务队列缓存PostgreSQL 存任务记录。三个服务在同一个自定义网络里通过服务名互相访问和宿主机网络隔离。version: 3.8 services: openclaw: image: openclaw/openclaw:custom container_name: openclaw restart: unless-stopped ports: - 8080:8080 volumes: - ./config:/config - ./data:/data - ./logs:/var/log/openclaw environment: - OPENCLAW_CONFIG/config/openclaw.yaml - OPENCLAW_LOG_LEVELINFO - OPENCLAW_LOG_FILE/var/log/openclaw/openclaw.log - TAOTOKEN_API_KEY${TAOTOKEN_API_KEY} - TAOTOKEN_BASE_URLhttps://taotoken.net/api - TAOTOKEN_MODELclaude-sonnet-4-20250514 networks: - openclaw-net depends_on: - redis - postgresql redis: image: redis:7-alpine container_name: openclaw-redis restart: unless-stopped volumes: - ./redis/data:/data command: redis-server --appendonly yes networks: - openclaw-net postgresql: image: postgres:15-alpine container_name: openclaw-postgresql restart: unless-stopped volumes: - ./postgresql/data:/var/lib/postgresql/data environment: - POSTGRES_DBopenclaw - POSTGRES_USERopenclaw - POSTGRES_PASSWORDopenclaw123 networks: - openclaw-net networks: openclaw-net: driver: bridge注意TAOTOKEN_API_KEY用的是${TAOTOKEN_API_KEY}变量引用你需要在同目录建一个.env文件内容如下TAOTOKEN_API_KEY你的实际Key.env文件不要提交到 git加到.gitignore里。这样 Key 通过环境变量注入容器不会写死在镜像或 compose 文件里。config/openclaw.yaml 是 OpenClaw 的主配置里面指定模型接入参数model: provider: taotoken base_url: https://taotoken.net/api api_key_env: TAOTOKEN_API_KEY model_id: claude-sonnet-4-20250514 storage: redis_host: redis redis_port: 6379 postgres_host: postgresql postgres_port: 5432 postgres_db: openclaw postgres_user: openclaw postgres_password: openclaw123 server: host: 0.0.0.0 port: 8080这里 redis_host 和 postgres_host 直接写服务名因为它们在同一个 Docker 网络里Docker 内置 DNS 会解析服务名到容器 IP。这就是环境隔离的一个体现容器之间用内部网络通信不暴露到宿主机也不依赖宿主机的 hosts 文件。目录结构整理一下~/openclaw-docker/ ├── Dockerfile ├── docker-compose.yml ├── .env ├── config/ │ └── openclaw.yaml ├── data/ ├── logs/ ├── redis/ │ └── data/ └── postgresql/ └── data/创建这些目录mkdir -p ~/openclaw-docker/{config,data,logs,redis/data,postgresql/data}配置写好后启动服务cd ~/openclaw-docker docker compose up -d用docker compose ps看三个容器是否都处于 running 状态。如果 openclaw 容器反复重启用docker compose logs openclaw看日志定位问题。4. 验证请求与成功结果端口连通、模型调用与隔离效果检查容器起来之后先确认端口连通。OpenClaw 的 HTTP 服务监听 8080映射到宿主机 8080。用 curl 请求健康检查接口curl -s http://localhost:8080/health正常返回类似{status:ok,version:1.0.0}。如果连接被拒绝先检查容器是否在运行再检查端口映射docker compose ps docker port openclawdocker port openclaw应该输出8080/tcp - 0.0.0.0:8080。如果没有输出说明 compose 里的 ports 配置没生效检查 yaml 缩进。接下来验证模型调用。OpenClaw 提供了一个测试接口可以发一条简单任务描述看它是否通过 TaoToken 调用模型并返回结果。用 curl 发 POST 请求curl -s -X POST http://localhost:8080/api/task \ -H Content-Type: application/json \ -d {description:move forward 1 meter}如果配置正确返回里会包含模型生成的动作序列类似{ task_id: abc123, status: completed, actions: [ {type: move, direction: forward, distance: 1.0} ] }如果返回 401说明 API Key 没传进去或无效。进容器检查环境变量docker exec openclaw env | grep TAOTOKEN应该能看到TAOTOKEN_API_KEY和TAOTOKEN_BASE_URL。如果 Key 是空的检查.env文件是否在 compose 同目录以及 compose 里变量名是否写对。如果返回里出现local proxy failed或连接超时说明容器内访问 TaoToken API 端点不通。先在容器里直接 curl 测试docker exec openclaw curl -s -o /dev/null -w %{http_code} https://taotoken.net/api返回 200 或 401 都说明网络通返回 000 说明 DNS 或路由有问题。检查 Docker 的 DNS 配置可以在 compose 的 openclaw 服务下加dns: 8.8.8.8或者检查宿主机防火墙是否拦截了容器出站流量。如果日志里出现reading choices相关报错通常是模型返回格式和 OpenClaw 预期不一致。检查TAOTOKEN_MODEL是否填了正确的 Model ID以及 TaoToken 的 API 是否支持该模型。可以先用模型对话页面单独测试同一个 Model ID确认能正常返回。隔离效果验证是这篇教程的重点之一。你要确认三件事第一容器内的依赖和宿主机隔离。在容器里查 Python 版本和 Boost 版本docker exec openclaw python3 --version docker exec openclaw dpkg -l | grep libboost然后在宿主机查同样的命令对比版本是否不同。如果宿主机没装这些库那更说明隔离生效了。第二容器间的网络隔离。Redis 和 PostgreSQL 没有映射端口到宿主机所以从宿主机直接连 6379 或 5432 应该失败nc -zv localhost 6379应该返回连接被拒绝。但在 openclaw 容器里可以连通docker exec openclaw nc -zv redis 6379 docker exec openclaw nc -zv postgresql 5432应该返回 succeeded。这就是自定义 bridge 网络的效果服务之间互通对外默认封闭。第三文件系统隔离。容器内的/config和/data是挂载的宿主机目录但容器内的其他路径比如/opt/openclaw是镜像层宿主机看不到。你在容器里改/opt/openclaw下的文件重建容器后就没了改/config下的文件宿主机同步可见。验证一下docker exec openclaw touch /opt/openclaw/test-isolation ls ~/openclaw-docker/config/ docker exec openclaw touch /config/test-persist ls ~/openclaw-docker/config/第一条 touch 在宿主机看不到第二条能看到。这帮你理解哪些数据需要持久化哪些可以随容器销毁。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth 报错对照部署过程中最容易遇到的几类报错这里逐个对照原因和解决方式。401 Unauthorized。表现是调用/api/task返回 401日志里显示invalid api key或authentication failed。原因通常是.env文件没被 compose 读取或者 Key 复制时带了空格。检查方式docker exec openclaw env | grep TAOTOKEN_API_KEY看值是否完整。如果值是空的确认.env文件和docker-compose.yml在同一目录并且 compose 里写的是${TAOTOKEN_API_KEY}。如果值有但报 401去 TaoToken 控制台 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 确认 Key 是否被禁用或删除。另外注意Key 只在创建时显示一次如果你复制的是页面上的掩码那肯定无效需要重新创建一个。local proxy failed。表现是容器内请求 TaoToken API 时连接失败日志里出现local proxy failed或connection refused。这个报错和代理工具无关纯粹是容器网络问题。先在容器里测 DNSdocker exec openclaw nslookup taotoken.net。如果解析失败给容器加 DNS 配置。在 compose 的 openclaw 服务下加dns: - 8.8.8.8 - 8.8.4.4然后docker compose up -d重建容器。如果 DNS 正常但连接超时检查宿主机是否能访问外网以及防火墙是否允许 Docker 网段出站。Docker 默认 bridge 网络的出站流量走 NAT一般不需要额外配置但某些云服务器安全组可能限制。reading choices 报错。表现是模型调用返回后OpenClaw 解析响应时抛异常日志里出现reading choices或cannot read property of undefined。原因是返回的 JSON 结构里没有choices字段通常是 API 返回了错误信息而不是正常响应。先看完整返回docker exec openclaw curl -s -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d {model:claude-sonnet-4-20250514,messages:[{role:user,content:hi}]}如果返回里有error字段根据错误信息处理。常见的是 Model ID 拼写错误或者该模型在当前账户下没有权限。确认 Model ID 和 TaoToken 文档里列出的一致。OAuth 相关报错。如果你在配置里误开了 OAuth 模式或者 OpenClaw 的某个插件尝试走 OAuth 流程会报oauth token missing或invalid grant。OpenClaw 接 TaoToken 用的是 API Key 模式不需要 OAuth。检查openclaw.yaml里 model 段是否有多余的oauth配置删掉即可。如果你用的是 Claude Code 类的工具接 TaoToken那走的是另一套配置参考接入文档里的说明不要混用。还有一个容易忽略的问题容器启动后端口不通但docker compose ps显示 running。这种情况多半是 OpenClaw 服务在容器内绑定到了 127.0.0.1 而不是 0.0.0.0。检查openclaw.yaml里server.host是否为0.0.0.0。如果是127.0.0.1容器外部无法访问改成0.0.0.0后重启容器。设备访问失败。如果你把 USB 设备映射进容器但 OpenClaw 报permission denied检查宿主机上设备节点的权限ls -l /dev/ttyUSB0如果属组是 dialout把当前用户加入 dialout 组或者给容器加privileged: true。但 privileged 权限过大更推荐用device_cgroup_rules精确控制。在 compose 里device_cgroup_rules: - c 188:* rmw188 是 ttyUSB 设备的主设备号。这样只放行 USB 串口设备比 privileged 安全。6. 语义一致 CTA从部署到持续调用OpenClaw 在 Docker 里跑起来之后你可以通过 8080 端口提交任务、查看状态、读取日志。整个环境是隔离的依赖不冲突数据通过挂载目录持久化重建容器不会丢配置和记录。如果你要更新 OpenClaw 版本改 Dockerfile 里的 git clone 分支或 tag重新 build 再 up 就行宿主机环境不受影响。日常调用模型时如果遇到 Key 管理或额度问题去控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 查看用量和 Key 状态。需要新建或轮换 Key在 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 操作。接入细节和参数说明在文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里容器内调用遇到格式问题可以先对照文档排查。如果你打算让 OpenClaw 长期跑自动化任务持续调用模型可以看看 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 的额度方案比按次调用更适合高频场景。模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 可以用来快速验证某个 Model ID 是否可用确认后再写进openclaw.yaml。最后提醒一点容器化部署的核心价值是隔离和可复现。你把 Dockerfile 和 compose 文件放进版本控制换一台机器docker compose up -d就能得到一模一样的环境。这比在宿主机上手动装依赖可靠得多。遇到问题时先看容器日志再进容器手动执行命令复现基本都能定位到配置层面的原因。