1. 为什么要把 OPENCLAW 关进 Docker 容器OPENCLAW 这类本地智能体工具跑起来很爽但它默认拿到的权限也很大能读你整个用户目录、能起后台进程、能访问网络。一旦它的行为链路出现偏差误读宿主机上的密钥文件、误删工作目录、或者被某个 prompt 诱导去执行不该执行的命令风险就直接落到你的真实系统上。我在 WSL2 Ubuntu 里裸跑过一段时间最直观的感受是它和宿主机之间几乎没有边界日志里出现一条奇怪的路径访问你很难判断是它主动扫的还是某个插件带进来的。Docker 容器化解决的正是这个边界问题。把 OPENCLAW 放进容器后文件系统隔离让容器只能看到你显式挂载进去的目录网络访问限制让它可以被约束在受控的出入口上后台进程也被锁在容器命名空间里。换句话说就算它真的跑偏了破坏半径也被限制在容器内部而不是你的整个 Windows 主机。这篇内容面向的是已经在 WSL2 Ubuntu 里跑过 OPENCLAW、现在想把它迁进 Docker 的开发者。我会给出可复制的 docker-compose.yml 骨架、.env 配置片段、数据卷挂载方式以及接入 TaoToken 统一 Key/API 通道的配置。整套流程在 WSL2 Ubuntu Docker Desktop 环境下实测可跑通重点放在迁移动作和验证动作上而不是从零讲 Docker 是什么。需要提前说明一点容器化不是万能药它只是把风险收窄。真正的安全还取决于你挂载了哪些目录、暴露了哪些端口、以及 API 通道是否可控。下面按落地顺序展开。2. 前置准备WSL2 Ubuntu 与 Docker 环境确认在动 OPENCLAW 之前先把底座确认清楚。Docker Desktop 依赖 WSL2如果你之前用的是 WSL1容器跑起来会各种奇怪报错。以管理员身份打开 PowerShell确认两个 Windows 功能已开启dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart执行完重启电脑然后把 WSL 默认版本设为 2并更新内核wsl --update wsl --set-default-version 2 wsl --install -d Ubuntu首次启动 Ubuntu 会提示创建用户名和密码按提示走完即可。接下来安装 Docker Desktop安装时务必勾选 “Use WSL 2 based engine”。装完启动等托盘图标变绿说明 Daemon 就绪。关键一步在设置里进入 Settings → Resources → WSL Integration勾选你刚装的 Ubuntu 发行版这样在 WSL Ubuntu 终端里才能直接调用 docker 命令。验证一下环境是否打通docker version docker compose version两条命令都能正常输出版本号说明 WSL2 Ubuntu 已经能驱动 Docker。如果docker version报 “Cannot connect to the Docker daemon”八成是 WSL Integration 没勾上或者 Docker Desktop 没启动。这里有个容易忽略的点OPENCLAW 在容器里需要 Node 环境。如果你打算在容器内构建基础镜像里要装 Node如果你是在宿主机 WSL 里先构建再打包那 WSL Ubuntu 里也要有 Node。用 NodeSource 装 Node 22curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - sudo apt-get install -y nodejs node -v3. TaoToken 前置统一 Key 与 API 通道OPENCLAW 这类工具通常要接大模型能力如果每个模型、每个环境都单独配一套 Key迁移到容器后环境变量会散得到处都是排查起来很痛苦。我的做法是统一走 TaoToken 的 API 通道一个 Key 覆盖多个模型调用容器里只注入一组环境变量迁移时直接复用。TaoToken 在这里扮演的是统一入口的角色你在控制台生成 API Key然后在 OPENCLAW 的配置里把 base_url 指向https://taotoken.net/api模型名按需填写。这样容器内的 OPENCLAW 不需要知道背后具体调的是哪家模型只认这一个通道。对迁移来说好处是 .env 文件里只有一组凭证从裸机搬到容器时不会漏配。具体动作分两步。第一步去控制台创建 Key# 控制台地址用于生成和管理 API Key https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite第二步在项目根目录准备 .env 文件把 Key 和 API 地址写进去。注意 .env 不要提交到 Git容器通过 env_file 读取即可。如果你还想在迁移前先验证模型通道是否通可以先用模型对话页面发一条测试消息# 模型对话入口验证 Key 与通道连通性 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite这一步的意义在于把「模型通道是否可用」和「容器是否跑起来」两个问题拆开验证。如果容器启动后调用失败你能快速判断是容器网络问题还是 Key 问题而不是混在一起猜。4. 可复制的 docker-compose.yml 与 .env 配置这是整篇的核心交付物。下面这份 docker-compose.yml 是我在 WSL2 Ubuntu 下实测可用的骨架包含 gateway 服务和 CLI 服务两部分数据卷、环境变量、重启策略都配好了。你可以直接复制到 OPENCLAW 源码目录下按自己的路径微调。services: openclaw-gateway: image: openclaw:local build: context: . dockerfile: Dockerfile container_name: openclaw-gateway env_file: - .env environment: - NODE_ENVproduction - OPENCLAW_HOME/home/node/.openclaw - OPENCLAW_WORKSPACE/home/node/.openclaw/workspace - OPENCLAW_ALLOWED_ORIGINShttp://localhost:3000,http://127.0.0.1:3000 volumes: - ./data/.openclaw:/home/node/.openclaw - ./data/workspace:/home/node/.openclaw/workspace - ./logs:/logs:rw ports: - 127.0.0.1:3000:3000 restart: unless-stopped healthcheck: test: [CMD, curl, -f, http://localhost:3000/health] interval: 30s timeout: 5s retries: 3 openclaw-cli: image: openclaw:local container_name: openclaw-cli env_file: - .env volumes: - ./data/.openclaw:/home/node/.openclaw - ./data/workspace:/home/node/.openclaw/workspace entrypoint: [node, dist/cli.js] profiles: - cli几个参数值得单独说。ports里我写的是127.0.0.1:3000:3000只绑定回环地址避免容器端口暴露到局域网。volumes把宿主机当前目录下的data/.openclaw和data/workspace挂进容器这样数据落在项目目录里迁移和备份都方便。healthcheck用 curl 探活配合restart: unless-stopped容器异常退出能自动拉起。对应的 .env 文件长这样# TaoToken 统一 API 通道 TAOTOKEN_API_KEYsk-你的实际Key TAOTOKEN_BASE_URLhttps://taotoken.net/api OPENCLAW_MODEL你的模型名 # OPENCLAW 运行参数 OPENCLAW_LOG_LEVELinfo OPENCLAW_CONTROL_UI_TOKEN自定义一个控制台token # 额外挂载与依赖包可选 OPENCLAW_EXTRA_MOUNTS/mnt/d/openclaw-docker/logs:/logs:rw OPENCLAW_DOCKER_APT_PACKAGESgit curl jq如果你是从官方脚本docker-setup.sh迁移过来的脚本会自动生成一份 docker-compose.yml但默认配置里控制 UI 的 Origins 限制比较严。容器内访问被识别为非回环地址所以必须在环境变量里显式声明OPENCLAW_ALLOWED_ORIGINS否则 gateway 会拒绝启动。这一点在迁移时最容易踩日志里会明确提示 origins 不匹配。构建和启动# 构建镜像 docker compose build # 后台启动 gateway docker compose up -d openclaw-gateway # 查看状态 docker compose psopenclaw-gateway的状态应该是Up并且 healthcheck 显示 healthy。如果状态是Restarting直接看日志定位。5. 数据迁移与接口连通性验证容器跑起来只是第一步真正要确认的是「旧数据迁进来了」和「模型通道能通」。数据迁移的核心是挂载路径对齐。官方脚本默认把宿主机的~/.openclaw和~/.openclaw/workspace绑到容器的/home/node/.openclaw和/home/node/.openclaw/workspace。如果你沿用这个路径不需要额外操作如果你像我一样把数据放到项目目录下的data/就要在启动前把旧数据复制过去。迁移动作建议这样走先停掉宿主机上裸跑的 gateway避免两边同时写同一份数据。# 停掉本地裸跑的 gateway openclaw gateway stop # 把旧数据复制到挂载目录 mkdir -p ./data/.openclaw ./data/workspace cp -a ~/.openclaw/. ./data/.openclaw/ cp -a ~/.openclaw/workspace/. ./data/workspace/复制完检查一下权限。容器默认以node用户UID 1000运行如果挂载目录属主不对容器会写不进去日志里报 permission denied。修正方式sudo chown -R 1000:1000 ./data然后启动容器验证接口连通性。先看容器状态docker compose ps docker compose logs -f openclaw-gateway日志里应该能看到 gateway 监听端口、加载配置、连接模型通道的记录。如果看到 origins 相关报错回去检查OPENCLAW_ALLOWED_ORIGINS。接着从容器内部探一下健康接口docker compose exec openclaw-gateway curl -s http://localhost:3000/health返回 200 或健康状态 JSON 就说明服务本身没问题。再验证模型通道用 CLI 发一条测试请求docker compose run --rm openclaw-cli channels login如果这一步能正常走完登录流程说明 TaoToken 的 Key 和 base_url 在容器内被正确读取网络出口也通。到这一步迁移基本完成。日常运维就三条命令docker compose up -d openclaw-gateway # 启动 docker compose stop openclaw-gateway # 停止 docker compose logs -f openclaw-gateway # 实时日志6. 本篇常见错误排查迁移过程中我踩过的坑集中在几类按出现频率排一下。第一类是docker: command not found。在 WSL Ubuntu 里执行 docker 命令报这个基本是 Docker Desktop 的 WSL Integration 没勾选对应发行版。回到 Settings → Resources → WSL Integration 勾上重启终端即可。如果是在 Git Bash 里跑注意路径要用/mnt/c/...形式。第二类是容器启动后立刻退出日志显示 origins 不匹配。这是 OPENCLAW 的安全机制控制 UI 默认只允许回环访问容器内被判定为非回环必须显式声明允许的域名。在 .env 里补上OPENCLAW_ALLOWED_ORIGINS值写你实际访问的地址比如http://localhost:3000。第三类是挂载目录写入失败日志报EACCES或permission denied。原因是宿主机目录属主不是 UID 1000。用sudo chown -R 1000:1000 path修正。另外注意别把挂载目录放在网络盘上性能差且容易出锁问题放本地 NTFS 分区最稳。第四类是模型调用超时或 401。先在模型对话页面确认 Key 有效再检查容器内 .env 是否被正确加载。可以用docker compose exec openclaw-gateway env | grep TAOTOKEN看环境变量有没有注入进去。如果 Key 对但请求失败检查TAOTOKEN_BASE_URL是否写成了https://taotoken.net/api少写或多写路径都会导致 404。第五类是 healthcheck 一直 unhealthy 但服务其实能用。多半是镜像里没装 curlhealthcheck 命令执行失败。要么在 Dockerfile 里补上 curl要么把 healthcheck 换成用 node 发请求。这个不影响功能但会让docker compose ps显示不健康容易误导。7. 后续接入与长期运行建议迁移完成后如果你打算长期在容器里跑 OPENCLAW 做编码或 Agent 任务建议把 API Key 的管理和调用配额也纳入统一通道。TaoToken 的 API Keys 页面可以集中管理凭证接入文档里有不同语言的调用示例容器里换 Key 只需要改 .env 再docker compose up -d重建不用动镜像。# API Keys 管理 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite # 接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite如果你的使用场景是长期编码、跑 Agent 工作流调用量比较稳定可以看一下 Coding Plan按套餐走比单次调用更划算也方便在容器环境里做配额控制。# Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite最后给一个实用建议容器化之后别急着把宿主机所有目录都挂进去。挂载越多隔离效果越弱。只挂 OPENCLAW 真正需要的工作目录和日志目录其余一律不挂。配合127.0.0.1端口绑定和显式 origins 白名单这套组合下来OPENCLAW 就被关进了一个边界清晰的笼子里既能干活又不会到处乱跑。