一、架构解析:理解 OpenClaw 的组件边界

一、架构解析:理解 OpenClaw 的组件边界

在编写 docker-compose.yml 之前,必须厘清 OpenClaw 的架构分层:

  1. Web Frontend (Next.js):提供可视化 Skill 编排界面,依赖 Node.js 运行时。
  2. API Server (Python/FastAPI):核心逻辑层,处理 Agent 调度、工具调用(Tool Use)与上下文管理。
  3. Worker (Celery):异步任务执行器,负责耗时操作(如文档解析、RAG 检索、外部 API 调用)。
  4. Message Broker (Redis):Celery 的任务队列后端,建议启用持久化防止任务丢失。
  5. Metadata DB (PostgreSQL):存储 Agent 配置、对话历史、用户权限等结构化数据。
  6. Vector Store (Qdrant/Milvus):可选组件,用于 RAG 场景的向量检索。

关键认知:Worker 与 API Server 必须共享相同的代码版本与环境变量,否则会出现序列化错误。


二、Docker Compose 编排实战

以下配置经过阿里云 ECS(2C4G)与本地 NAS(QNAP TS-464C)双环境验证,针对国内网络环境优化了镜像源与构建策略。

version: "3.8"

services:
  # 1. PostgreSQL 主库
  postgres:
    image: postgres:15-alpine
    container_name: openclaw_db
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${DB_USER:-openclaw}
      POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme}
      POSTGRES_DB: ${DB_NAME:-openclaw_prod}
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
      - ./init-scripts:/docker-entrypoint-initdb.d  # 初始化 SQL
    networks:
      - openclaw_net
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
      interval: 10s
      timeout: 5s
      retries: 5

  # 2. Redis 消息队列
  redis:
    image: redis:7-alpine
    container_name: openclaw_redis
    restart: unless-stopped
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-redis123}
    volumes:
      - ./data/redis:/data
    networks:
      - openclaw_net

  # 3. API Server 主服务
  api:
    build:
      context: ./backend
      dockerfile: Dockerfile.prod  # 使用多阶段构建减少体积
    container_name: openclaw_api
    restart: unless-stopped
    environment:
      - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}
      - REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379/0
      - SECRET_KEY=${SECRET_KEY:-your-secret-key-here}
      - LLM_API_KEY=${LLM_API_KEY}  # 阿里云百炼或 OpenAI Key
      - LLM_BASE_URL=${LLM_BASE_URL:-https://dashscope.aliyuncs.com/compatible-mode/v1}
      - LOG_LEVEL=INFO
    volumes:
      - ./logs:/app/logs
      - ./uploads:/app/uploads  # 文件上传目录
    networks:
      - openclaw_net
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # 4. Celery Worker 异步任务
  worker:
    build:
      context: ./backend
      dockerfile: Dockerfile.prod
    container_name: openclaw_worker
    restart: unless-stopped
    command: celery -A app.core.celery worker -l info -c 4  # 并发数4
    environment:
      - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}
      - REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379/0
      - SECRET_KEY=${SECRET_KEY}
      - LLM_API_KEY=${LLM_API_KEY}
      - LLM_BASE_URL=${LLM_BASE_URL}
      - PYTHONPATH=/app
    volumes:
      - ./logs:/app/logs
      - ./uploads:/app/uploads
    networks:
      - openclaw_net
    depends_on:
      - redis
      - postgres

  # 5. Frontend 前端界面
  web:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    container_name: openclaw_web
    restart: unless-stopped
    environment:
      - NEXT_PUBLIC_API_URL=http://api:8000  # 内部通信
      - NEXT_PUBLIC_WS_URL=ws://api:8000/ws
    networks:
      - openclaw_net
    depends_on:
      - api

  # 6. Nginx 反向代理(生产必需)
  nginx:
    image: nginx:alpine
    container_name: openclaw_nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro  # SSL证书
      - ./logs/nginx:/var/log/nginx
    networks:
      - openclaw_net
    depends_on:
      - web
      - api

networks:
  openclaw_net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

volumes:
  postgres_data:
  redis_data:

关键配置解析

  1. 健康检查(Healthcheck):PostgreSQL 和 API 服务均配置了健康检查,避免服务未就绪时导致依赖方启动失败。
  2. 资源限制:Worker 通过 -c 4 限制并发数为 4,防止低配置服务器(2C4G)因并发过高导致 OOM。
  3. 网络隔离:自定义 openclaw_net 网段(172.20.0.0/16),避免与宿主机现有网络冲突。

三、生产环境踩坑实录

1. 权限陷阱:容器内非 root 运行

默认情况下,Celery Worker 若以 root 运行,会触发 Python 的 RuntimeWarning,且存在安全风险。需在 Dockerfile.prod 中显式创建用户:

# Dockerfile.prod 片段
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
RUN chown -R appuser:appgroup /app/logs /app/uploads
USER appuser

坑点:若宿主机挂载的 ./logs 目录权限为 root,容器内非 root 用户将无写入权限,导致 Worker 启动失败。解决命令:

chown -R 1000:1000 ./logs ./uploads  # 1000 为容器内 appuser 的 UID

2. 数据库连接池耗尽

OpenClaw 默认使用 SQLAlchemy 的默认连接池配置,在高并发场景下(如批量导入文档),极易触发 FATAL: sorry, too many clients already

解决方案:在 API 和 Worker 的环境变量中增加连接池配置:

environment:
  - DATABASE_POOL_SIZE=10
  - DATABASE_MAX_OVERFLOW=20
  - DATABASE_POOL_RECYCLE=3600

并在 PostgreSQL 侧调整 max_connections

# 在 init-scripts/01-config.sql 中
ALTER SYSTEM SET max_connections = 200;

3. 国内网络下的模型 API 超时

默认配置下,OpenClaw 请求阿里云百炼或 OpenAI API 时,若宿主机位于国内且未配置代理,常因网络抖动导致 ReadTimeout

硬核解决方案:在 Docker Compose 中注入代理环境变量,并配置 DNS:

services:
  api:
    environment:
      - HTTP_PROXY=http://host.docker.internal:7890  # Clash 宿主机代理
      - HTTPS_PROXY=http://host.docker.internal:7890
      - NO_PROXY=postgres,redis,localhost,127.0.0.1
    dns:
      - 223.5.5.5  # 阿里 DNS,避免运营商 DNS 污染
      - 8.8.8.8
  worker:
    environment:
      - HTTP_PROXY=http://host.docker.internal:7890
      - HTTPS_PROXY=http://host.docker.internal:7890

注意:若使用 host 网络模式,需将 host.docker.internal 替换为宿主机实际内网 IP。


四、性能调优与监控

1. 资源限制与 OOM 防护

生产环境务必设置内存限制,防止某个服务内存泄漏拖垮整台宿主机:

services:
  worker:
    deploy:
      resources:
        limits:
          cpus: '1.5'
          memory: 2G
        reservations:
          cpus: '0.5'
          memory: 512M

2. 日志轮转(Logrotate)

容器默认日志存储于 JSON 文件,长期运行会撑爆磁盘。需在宿主机配置 logrotate:

# /etc/logrotate.d/docker-container-logs
/var/lib/docker/containers/*/*.log {
    rotate 7
    daily
    compress
    size=100M
    missingok
    delaycompress
    copytruncate
}

或使用 Docker 自带的日志驱动限制:

services:
  api:
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "3"

结语

OpenClaw 的出现,标志着个人或中小团队构建私有化 AI Agent 工作流的门槛已大幅降低。通过 Docker Compose 进行自托管,不仅能完全掌控数据主权,更能基于内部业务系统深度定制 Skill 工具链。

然而,生产级部署绝非简单的 docker-compose up -d。从数据库连接池调优、容器权限管控到网络代理的精细配置,每一个细节都关乎系统的稳定性与安全性。希望本文的硬核拆解,能帮助你在私有化部署的道路上避开那些我曾踩过的深坑。

你目前在部署 OpenClaw 或类似的 AI Agent 平台时遇到了哪些棘手问题?欢迎在评论区分享你的报错日志与架构设计,我们一起探讨更优雅的解法。

Licensed under CC BY-NC-SA 4.0