Docker Compose 部署 OpenClaw:从单机到生产级集群的完整指南
2026/8/4 9:18:07 网站建设 项目流程

1. 从单机到集群:为什么我们需要一个生产级的 OpenClaw 部署方案?

如果你最近在折腾 AI 应用,尤其是想自己搞一个能调用各种大模型、集成各种工具的智能体平台,那“OpenClaw”这个名字你肯定不陌生。它就像一个功能强大的“AI 副驾驶”框架,能帮你把 GPT、Claude、本地模型甚至各种 API 工具串联起来,实现自动化工作流。很多朋友在本地用docker run或者直接跑源码,体验一下基础功能就满足了。但一旦你想把它用起来,比如给团队用、或者部署到服务器上长期运行,马上就会遇到一堆头疼事:环境依赖冲突、配置文件散落各处、服务挂了得手动重启、想加个 Redis 缓存或者数据库都得重新折腾一遍。

这就是为什么我今天要跟你详细聊聊,如何用Docker Compose把 OpenClaw 从一个“玩具”升级为“生产级”的分布式爬虫平台(这里“爬虫”更广义地指代其自动化数据抓取与处理能力)。我见过太多人卡在部署这一步,不是端口冲突就是容器网络不通,最后只能放弃。实际上,一套好的容器化方案,能让你像搭积木一样管理 OpenClaw 的各个组件,实现高可用、易扩展和运维自动化。接下来,我不会只给你一个干巴巴的docker-compose.yml文件,而是会拆解每一个配置项背后的设计逻辑,分享我在实际部署中踩过的坑和验证过的优化技巧,让你真正掌握从零到一构建稳健 OpenClaw 服务集群的方法。

2. 生产级部署的核心诉求与架构设计

在动手写一行 Docker 配置之前,我们必须先想清楚:一个“生产级”的 OpenClaw 到底需要什么?它和我们在笔记本上快速体验的版本有本质区别。

2.1 明确生产环境的四大核心需求

首先,高可用性是最基本的要求。这意味着核心服务(如 Web UI、API 网关、模型调度器)不能有单点故障。简单跑一个容器,宿主机重启或者容器崩溃,服务就中断了,这绝对不行。我们需要设计多副本、健康检查以及故障自动恢复机制。

其次,配置与数据持久化是保证服务可维护性的关键。OpenClaw 运行需要模型文件、技能插件配置、对话历史、用户数据等。这些绝不能存放在容易丢失的容器内部文件系统中。我们必须通过卷(Volume)或绑定挂载(Bind Mount)的方式,将关键数据持久化到宿主机或网络存储上,确保升级、重启甚至迁移容器时,数据完好无损。

第三,可观测性与日志聚合。当服务出问题时,你需要快速定位是哪个组件、哪行代码、哪个模型调用导致了异常。生产环境下,日志不能再简单地输出到容器的标准输出然后被 Docker 日志驱动收集就完事了。我们需要将 OpenClaw 自身日志、模型服务日志、访问日志等统一收集、结构化存储,并配合监控指标(如请求延迟、错误率、GPU 显存使用率)进行告警。

第四,安全与网络隔离。OpenClaw 可能会访问内部数据库、调用敏感 API,其 Web 服务也可能暴露在公网。我们需要在容器层面做好网络规划,区分前端、后端、数据库等不同网络区域,并妥善管理敏感信息(如 API Keys、数据库密码),绝不能硬编码在镜像或配置文件里。

2.2 基于 Docker Compose 的分布式架构蓝图

基于以上需求,我设计了一个分层、模块化的架构,用 Docker Compose 来编排。这个架构的核心思想是“服务拆分”“依赖外置”

服务拆分是指,我们不把 OpenClaw 的所有功能塞进一个“巨无霸”容器。相反,我们将其拆分为多个独立的服务:

  1. openclaw-core: 核心服务,包含 Web UI 和主要 API。这是用户交互的入口。
  2. openclaw-worker: 工作节点,负责执行具体的技能(Skills)和模型调用。你可以根据负载水平,轻松扩展多个worker实例。
  3. model-service-*: 模型服务层。例如,一个服务专门跑Llama.cpp,一个服务连接 OpenAI 兼容的 API(如 LocalAI 或 vLLM)。这样,模型服务的生命周期、资源隔离和版本升级就与 OpenClaw 核心解耦了。
  4. redis: 作为缓存和消息队列(Celery broker)。用于存储会话状态、管理任务队列,实现coreworker之间的异步通信。
  5. postgres(可选): 用于持久化存储结构化数据,如用户信息、对话历史、技能配置元数据等。如果数据量不大,用 SQLite 也可以,但 PostgreSQL 在并发和可靠性上更胜一筹。

依赖外置是指,将 Redis、PostgreSQL 甚至模型文件,都作为外部依赖服务或卷来管理,而不是打包进 OpenClaw 镜像。这样做的好处是,每个服务都可以独立升级、伸缩和备份。

整个系统的数据流大致是这样的:用户通过openclaw-core的 WebUI 或 API 发起请求 ->core将任务发布到redis队列 -> 某个空闲的openclaw-worker从队列获取任务 ->worker根据任务类型,调用对应的model-service或执行本地技能 -> 结果写回redispostgres->core将结果返回给用户。这个流程天然支持分布式和横向扩展。

3. 手把手构建 Docker Compose 编排文件

理解了架构,我们现在来编写核心的docker-compose.yml文件。我会逐部分解释,并给出生产环境的最佳实践配置。

3.1 网络与卷定义:打好基础设施的地基

首先定义网络和持久化卷,这是服务间通信和数据持久化的基础。

version: '3.8' networks: openclaw-net: driver: bridge # 为网络指定一个自定义的子网,避免与宿主机或其他Docker网络冲突 ipam: config: - subnet: 172.22.0.0/24 volumes: openclaw_data: # 使用命名卷,由Docker管理存储位置,适合存储应用数据 driver: local postgres_data: # 数据库数据单独存储 driver: local redis_data: # Redis数据持久化 driver: local model_cache: # 用于缓存从网上下载的模型文件,避免重复下载 driver: local

注意:对于生产环境,更推荐将postgres_dataredis_data这类关键数据卷,配置为使用driver: local并指定具体路径,或者直接使用 NFS、Ceph 等支持多主机访问的驱动,以便于备份和迁移。简单的driver: local在单机部署时够用。

3.2 核心服务配置:OpenClaw Core 与 Worker

接下来是 OpenClaw 自身的服务。这里有一个关键点:我们需要一个基础镜像,并让coreworker都基于它。

services: openclaw-core: build: context: ./openclaw dockerfile: Dockerfile container_name: openclaw-core hostname: openclaw-core restart: unless-stopped ports: - "3000:3000" # WebUI 端口 - "8080:8080" # API 端口 (假设) environment: - NODE_ENV=production - REDIS_URL=redis://redis:6379/0 - DATABASE_URL=postgresql://postgres:your_secure_password@postgres:5432/openclaw - OPENCLAW_API_KEY=${OPENCLAW_API_KEY:-} # 从环境变量文件读取 - OPENCLAW_MODEL_ENDPOINT_LLAMA=http://model-service-llama:8080/v1 volumes: - openclaw_data:/app/data - ./config:/app/config:ro # 挂载本地配置文件,ro表示只读 - ./logs/core:/app/logs networks: - openclaw-net depends_on: - redis - postgres - model-service-llama healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s openclaw-worker: build: context: ./openclaw dockerfile: Dockerfile container_name: openclaw-worker-1 hostname: openclaw-worker-1 restart: unless-stopped environment: - NODE_ENV=production - ROLE=worker - REDIS_URL=redis://redis:6379/0 - DATABASE_URL=postgresql://postgres:your_secure_password@postgres:5432/openclaw volumes: - openclaw_data:/app/data - ./config:/app/config:ro - ./logs/worker:/app/logs networks: - openclaw-net depends_on: - redis - postgres deploy: replicas: 2 # 使用Docker Swarm模式时可以指定副本数,普通compose运行时此字段无效,但表达了扩展意图。 # 普通compose下,想启动多个worker,可以将其定义复制一份,并修改container_name和hostname,或者使用scale命令。

关键配置解读与避坑指南:

  1. build上下文:我假设你的项目根目录下有一个./openclaw文件夹,里面包含了 OpenClaw 的源码和Dockerfile。这样编排文件更清晰。
  2. 环境变量ROLE:这是我在Dockerfile或 OpenClaw 启动脚本中会读取的一个变量,用于决定容器是启动core(Web服务)还是worker(后台任务处理)。这是一种常见的多角色镜像模式。
  3. depends_on:它只控制启动顺序,保证依赖服务已“就绪”。这就是为什么我们需要healthcheck。上面为openclaw-core配置了健康检查,只有当它自己能通过/health端点返回成功时,Docker 才认为它是健康的。其他服务(如 Postgres, Redis)也应该配置健康检查,这样depends_on结合健康检查才能真正实现“等待就绪”。
  4. 端口暴露:只将必要的端口(如 WebUI 的 3000)映射到宿主机。API端口(8080)可以考虑不映射,而是通过反向代理(如 Nginx)来访问,增加安全性。
  5. 敏感信息管理:像DATABASE_URL中的密码、OPENCLAW_API_KEY,绝对不要写死在docker-compose.yml里。示例中使用了${OPENCLAW_API_KEY:-}语法,它会尝试从名为.env的环境变量文件中读取。你需要在项目根目录创建.env文件,并确保它被.gitignore排除,内容如下:
    OPENCLAW_API_KEY=your_super_secret_api_key_here POSTGRES_PASSWORD=your_secure_password
    然后在docker-compose.yml中引用:DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/openclaw

3.3 依赖服务配置:数据库、缓存与模型服务

现在配置外围的支撑服务。

postgres: image: postgres:15-alpine container_name: openclaw-postgres restart: unless-stopped environment: POSTGRES_DB: openclaw POSTGRES_USER: postgres POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro # 初始化脚本 networks: - openclaw-net healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine container_name: openclaw-redis restart: unless-stopped command: redis-server --appendonly yes # 开启AOF持久化 volumes: - redis_data:/data networks: - openclaw-net healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 model-service-llama: image: ghcr.io/ggerganov/llama.cpp:server-latest container_name: openclaw-llama-server restart: unless-stopped ports: - "8081:8080" # 将容器内8080映射到宿主机的8081,避免与openclaw-core的API端口冲突 environment: - MODEL=/models/llama-2-7b.gguf - N_GPU_LAYERS=20 # 根据你的GPU调整 - CONTEXT_SIZE=4096 volumes: - model_cache:/models # 假设模型文件已预先下载到宿主机的某个目录,并挂载到/model_cache,再软链接或复制到/models - ./models:/models:ro # 另一种方式:直接挂载宿主机的模型目录 networks: - openclaw-net deploy: resources: reservations: devices: - driver: nvidia count: 1 capabilities: [gpu] # 申请GPU资源,需要nvidia-container-toolkit

关键配置解读与避坑指南:

  1. PostgreSQL 初始化:通过./init.sql挂载,你可以在数据库首次启动时自动创建表、索引或初始化数据。这对于确保应用所需的数据库结构就绪非常有用。
  2. Redis 持久化--appendonly yes开启了 AOF 持久化,即使容器重启,只要数据卷 (redis_data) 还在,数据就不会丢失。对于任务队列这种场景,这很重要,可以避免任务丢失。
  3. 模型服务:这里以llama.cpp的 server 镜像为例。这是最容易出问题的地方。首先,模型文件 (llama-2-7b.gguf) 需要你提前准备好。我强烈建议在宿主机上维护一个统一的模型存储目录,然后通过卷挂载给不同的模型服务容器使用,避免每个容器都下载一遍,浪费磁盘空间和网络带宽。
  4. GPU 支持:如果你想让模型服务使用 GPU,需要在宿主机上安装nvidia-container-toolkit,并在docker-compose.yml中像上面那样配置deploy.resources。同时,llama.cpp服务器的镜像可能需要支持 CUDA 的版本,注意选择正确的镜像标签。
  5. 端口规划:模型服务的端口映射到宿主机一个非标准端口(如 8081),主要是为了调试方便。在生产中,这些内部服务(模型服务、Redis、Postgres)的端口不应该直接暴露给宿主机,只应在openclaw-net这个自定义网络内互通。这样可以减少攻击面。外部访问只通过openclaw-core的 WebUI 或 API 网关。

4. 编写 OpenClaw 的 Dockerfile 与配置

Docker Compose 定义了服务关系,但每个服务具体怎么构建,取决于Dockerfile。下面是一个 OpenClaw 多角色镜像的Dockerfile示例,它可以根据环境变量启动不同的进程。

# ./openclaw/Dockerfile FROM node:18-slim AS builder WORKDIR /app # 复制依赖定义文件 COPY package*.json ./ COPY yarn.lock ./ # 安装依赖(包括devDependencies,用于构建) RUN yarn install --frozen-lockfile # 复制源码并构建 COPY . . RUN yarn build # 生产运行阶段 FROM node:18-slim AS runner WORKDIR /app ENV NODE_ENV=production # 安装仅运行时需要的依赖 COPY package*.json ./ COPY yarn.lock ./ RUN yarn install --frozen-lockfile --production # 从构建阶段复制构建产物和必要的文件 COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules # 复制配置文件模板、启动脚本等 COPY docker-entrypoint.sh ./ COPY config/config.production.example.json ./config/ # 创建非root用户运行,增强安全性 RUN addgroup --system --gid 1001 openclaw && \ adduser --system --uid 1001 openclaw USER openclaw # 声明数据卷,方便持久化 VOLUME ["/app/data", "/app/logs"] # 使用入口点脚本,根据环境变量决定启动模式 ENTRYPOINT ["./docker-entrypoint.sh"]

对应的入口点脚本docker-entrypoint.sh

#!/bin/sh set -e # 根据 ROLE 环境变量启动不同的进程 if [ "$ROLE" = "worker" ]; then echo "Starting OpenClaw worker..." exec node dist/worker.js else # 默认为 core 角色 echo "Starting OpenClaw core (web+api)..." # 可以在这里运行数据库迁移等前置操作 # node dist/migrate.js exec node dist/server.js fi

关键配置解读与避坑指南:

  1. 多阶段构建:使用builder阶段安装所有依赖并构建,在runner阶段只复制运行所需的最小文件集。这可以显著减小最终镜像的体积,提高安全性(因为构建工具不会留在生产镜像中)。
  2. 非 Root 用户:使用USER openclaw指令让容器以非 root 用户运行,这是一个重要的安全最佳实践,可以限制容器被入侵后的影响范围。
  3. 配置管理:将配置文件(如config.production.example.json)复制到镜像中。在容器启动时,可以通过环境变量或挂载外部配置文件的方式来覆盖它。更灵活的做法是,在docker-compose.yml中完全通过volumes挂载一个外部的config目录,这样修改配置无需重建镜像。
  4. 数据卷声明VOLUME指令声明了/app/data/app/logs为卷。这有两个作用:一是文档化,告诉使用者这些路径用于存储持久化数据;二是即使运行时不指定-v挂载,Docker 也会自动创建匿名卷,防止数据丢失在可写层(虽然生产环境一定要显式挂载命名卷)。

5. 部署、运维与故障排查实战

有了编排文件和镜像,我们就可以部署了。但部署只是开始,运维才是重头戏。

5.1 一键启动与日常操作

在包含docker-compose.yml的目录下,执行以下命令:

# 1. 构建镜像并启动所有服务(后台运行) docker-compose up -d --build # 2. 查看所有容器状态 docker-compose ps # 3. 查看特定服务的日志(实时跟踪) docker-compose logs -f openclaw-core # 4. 进入某个容器的shell(用于调试) docker-compose exec openclaw-core /bin/sh # 5. 停止所有服务 docker-compose down # 6. 停止服务并删除数据卷(危险!会丢失所有数据) # docker-compose down -v # 7. 重启某个服务(例如修改了worker的配置后) docker-compose restart openclaw-worker # 8. 扩展worker实例数量(假设你在compose文件中定义了worker服务) docker-compose up -d --scale openclaw-worker=3

5.2 生产环境必须考虑的进阶配置

  1. 资源限制:在docker-compose.yml中为每个服务添加deploy.resources.limits,防止某个容器耗尽宿主机资源。

    services: openclaw-core: # ... deploy: resources: limits: cpus: '1.0' memory: 1G
  2. 日志驱动与收集:默认的json-file日志驱动可能不够。可以配置为journald(如果宿主机用 systemd)或syslog。更好的做法是使用FluentdLoki等日志收集器。可以在docker-compose.yml全局或服务级配置:

    logging: driver: "json-file" options: max-size: "10m" max-file: "3"
  3. 使用反向代理:不要将 OpenClaw 的端口直接暴露给公网。使用 Nginx 或 Traefik 作为反向代理,可以提供 HTTPS、负载均衡、访问控制、速率限制等能力。这通常需要在 Docker Compose 中添加一个nginxtraefik服务。

  4. 备份策略:定期备份postgres_dataopenclaw_data卷。可以使用docker run --volumes-from临时容器来执行备份命令,或者直接备份宿主机上 Docker 管理的卷目录(通常位于/var/lib/docker/volumes/)。

5.3 常见故障排查链路

当你遇到问题,比如 OpenClaw WebUI 打不开,可以按照以下链路排查:

  1. 检查容器状态docker-compose ps。确认所有服务的状态都是Up。如果有ExitRestarting,进入下一步。
  2. 查看错误日志docker-compose logs [service-name]。这是最重要的信息源。常见错误:
    • 数据库连接失败:检查DATABASE_URL环境变量、PostgreSQL 容器是否健康、网络是否互通(docker-compose exec openclaw-core ping postgres)。
    • Redis 连接失败:类似数据库,检查REDIS_URL和 Redis 容器状态。
    • 模型服务连接失败:检查OPENCLAW_MODEL_ENDPOINT_LLAMA的 URL 和端口是否正确,模型服务容器是否健康,模型文件路径是否存在。
    • 端口冲突:检查宿主机端口(3000, 8080等)是否已被其他程序占用。
  3. 检查网络docker network inspect openclaw_openclaw-net(网络名通常是项目名_网络名)。确认所有服务都在同一个网络中,并且有正确的 IP 地址。
  4. 进入容器内部调试docker-compose exec openclaw-core /bin/sh。在容器内尝试执行curl http://redis:6379curl http://postgres:5432(虽然不能直接 curl 数据库,但可以测通断),验证服务间通信。
  5. 检查卷挂载docker inspect openclaw-core,查看Mounts部分,确认数据卷是否正确挂载,权限是否正确(尤其是以非 root 用户运行时,挂载的宿主机目录需要有相应权限)。

一个我踩过的具体坑是:OpenClaw Worker 一直报错,无法从 Redis 获取任务。日志显示连接 Redis 超时。排查后发现,在docker-compose.yml中,Worker 服务依赖了 Redis,但 Redis 容器虽然启动了,其服务却未完全就绪(加载 AOF 文件较慢)。depends_on只保证了启动顺序,没保证就绪状态。解决方案:为 Redis 服务添加了上面提到的healthcheck,并在 Worker 服务的启动命令或应用代码中,增加对 Redis 连接的重试逻辑,问题得以解决。

6. 从 Compose 走向更高阶的编排

Docker Compose 非常适合单机部署和小型生产环境。当你的 OpenClaw 平台需要面对更高并发、要求真正的多节点高可用时,就需要考虑更强大的编排工具,比如Kubernetes (K8s)

将现有的 Docker Compose 配置迁移到 K8s 是一个自然的演进路径。你可以将每个service转换为一个 K8sDeployment(用于无状态服务,如openclaw-core,openclaw-worker)或StatefulSet(用于有状态服务,如postgres,redis)。docker-compose.yml中的networks对应 K8s 的ServiceIngressvolumes对应PersistentVolumeClaim(PVC)。

在 K8s 中,你可以轻松实现:

  • 自动扩缩容:根据 CPU/内存使用率或自定义指标(如任务队列长度)自动增加或减少openclaw-worker的 Pod 数量。
  • 滚动更新与回滚:无缝更新 OpenClaw 版本,如果出现问题可以一键回滚到上一个稳定版本。
  • 更精细的资源管理与调度:将 GPU 密集型任务(模型服务)调度到带有 GPU 的节点,将 IO 密集型任务调度到 SSD 存储节点。
  • 强大的服务发现与负载均衡:无需手动管理 IP 和端口。

虽然 K8s 的学习曲线更陡峭,但它为 OpenClaw 这类分布式应用提供了企业级的运维能力。如果你的业务在增长,提前规划容器编排的演进路线是很有价值的。你可以先从 Docker Compose 稳定运行开始,同时将 K8s 的 manifest 文件(如deployment.yaml,service.yaml)作为另一个版本的部署描述符来维护,为未来平滑过渡做好准备。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询