OpenClaw 技能依赖安装与公众号发布完整教程

2 阅读4分钟

写在前面

今天下午,我想给 OpenClaw 安装一个微信公众号发布技能 wechat-article-publisher,把文章一键发布到公众号草稿箱。

技能安装很顺利,但在飞书执行“发布到公众号草稿箱”时,遇到了一系列问题:

  • ModuleNotFoundError: No module named 'requests'(依赖缺失)
  • Read-only file system(只读权限)
  • Permission denied(权限不足)
  • No usable temporary directory(无临时目录)
  • 最后还有封面图片写入失败的问题

从下午 1 点折腾到晚上 6 点,整整 5 个小时。写下这篇教程,记录踩过的每一个坑和最终解决方案。


一、问题根源

问题原因
依赖缺失容器没有 pip,也没装 Python 依赖
只读错误read_only: true 导致无法写入
权限错误非 root 用户无安装权限
apt-get 慢用了国外源
依赖重启丢失手动装在了容器内,不是镜像里
临时目录不可写/tmp 只读
封面图片写入失败技能脚本试图写入只读的 skills/assets 目录

核心教训:不要在运行时手动装依赖,要把所有依赖打包进 Docker 镜像。


二、最终解决方案

2.1 Dockerfile(依赖打包进镜像)

FROM ghcr.nju.edu.cn/openclaw/openclaw:latest
USER root

# 强制阿里云源(加速 apt-get)
RUN rm -rf /etc/apt/sources.list.d/* 2>/dev/null || true && \
    echo "deb http://mirrors.aliyun.com/debian bookworm main" > /etc/apt/sources.list && \
    echo "deb http://mirrors.aliyun.com/debian bookworm-updates main" >> /etc/apt/sources.list && \
    echo "deb http://mirrors.aliyun.com/debian-security bookworm-security main" >> /etc/apt/sources.list

# 安装 pip
RUN apt-get update && apt-get install -y python3-pip cron && rm -rf /var/lib/apt/lists/*

# 安装 wechat-article-publisher 技能所需的依赖
RUN python3 -m pip install --break-system-packages \
    -i https://pypi.tuna.tsinghua.edu.cn/simple \
    requests beautifulsoup4 markdown pyyaml Pillow

USER node

2.2 docker-compose.yml(关键配置)

services:
  openclaw:
    build: .
    container_name: openclaw-gateway
    restart: unless-stopped

    # 安全配置(全部开启)
    cap_drop:
      - ALL
    cap_add:
      - DAC_OVERRIDE
    read_only: true
    tmpfs:
      - /tmp              # 让 /tmp 可写(解决临时文件问题)
    user: "1000:1000"
    security_opt:
      - no-new-privileges:true

    ports:
      - "127.0.0.1:37406:18789"

    volumes:
      - ./config:/home/node/.openclaw:rw
      - ./workspace:/home/node/.openclaw/workspace:rw
      - ./logs:/home/node/logs:rw
      - ./data:/home/node/data:rw
      - ./credentials:/home/node/.openclaw/credentials:ro
      - ./skills:/home/node/.openclaw/skills:ro   # 技能目录保持只读
      - ./extensions:/home/node/.openclaw/extensions:ro
      - ./agents:/home/node/.openclaw/agents:rw
      - ./tmp/openclaw-1000:/tmp/openclaw-1000:rw
      - ./npm:/home/node/.npm:rw

    environment:
      - NODE_ENV=production
      - LOG_LEVEL=info
      - OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_TOKEN}
      # ... 其他环境变量

2.3 修改技能脚本(解决封面图片写入问题)

技能脚本试图写入只读的 skills/assets 目录,需要改为写入 /tmp

# 修改脚本中的临时目录
sed -i 's|Path(__file__).resolve().parent.parent / "assets" / "generated_cover.jpg"|Path("/tmp") / "generated_cover.jpg"|g' \
skills/wechat-article-publisher-1/scripts/publish_wechat.py

三、构建与验证

3.1 首次构建

cd /opt/openclaw
docker compose build --no-cache
docker compose up -d

3.2 验证依赖

docker exec -it openclaw-gateway python3 -c "import requests, bs4, markdown, yaml, PIL; print('✅ 依赖齐全')"

3.3 配置公众号凭证

在飞书里发送:

这是我的公众号配置,请帮我写入到公众号发布技能中

AppID:你的AppID
AppSecret:你的AppSecret

3.4 测试发布

在飞书里发送:

发布到公众号草稿箱

或先生成一篇文章再发布:

帮我写一篇关于AI的公众号文章,发布到公众号草稿箱

四、以后的操作

日常升级

cd /opt/openclaw
docker compose down
docker compose build --no-cache
docker compose up -d

日常重启

docker compose restart

验证依赖是否正常

docker exec -it openclaw-gateway python3 -c "import requests; print('✅ OK')"

五、踩坑清单与解决方案汇总

序号错误现象原因解决方案
1pip3: command not found容器没装 pipDockerfile 中安装 python3-pip
2Read-only file systemread_only: true依赖打包进镜像,不在运行时安装
3Permission denied非 root 用户构建时用 root,运行时切回 node
4apt-get update 极慢国外源强制换阿里云源
5依赖重启就丢手动装在容器内依赖打包进镜像
6ModuleNotFoundErrorPYTHONPATH 不对依赖装到系统默认路径
7No usable temporary directory/tmp 只读添加 tmpfs: - /tmp
8封面图片写入失败脚本写入只读的 skills/assets修改脚本,改为写入 /tmp

六、快速排障清单

如果发布失败,按顺序检查:

# 1. 检查依赖
docker exec -it openclaw-gateway python3 -c "import requests; print('OK')"

# 2. 检查技能目录
docker exec -it openclaw-gateway ls -la /home/node/.openclaw/skills/ | grep wechat

# 3. 检查配置
docker exec -it openclaw-gateway cat /home/node/.openclaw/skills/wechat-article-publisher-1/config.json

# 4. 查看错误日志
docker compose logs --tail 50 | grep -i error

# 5. 检查 /tmp 是否可写
docker exec -it openclaw-gateway touch /tmp/test.txt && echo "可写"

七、一句话总结

把依赖打包进 Docker 镜像,装到系统默认路径,用 tmpfs 让 /tmp 可写,修改技能脚本使用 /tmp 作为临时目录,换好国内源——一次构建,永久省心。


八、对比:错误方案 vs 正确方案

对比项错误方案正确方案
依赖位置运行时手动装打包进镜像
重启后❌ 丢失✅ 还在
重建后❌ 丢失✅ 还在
迁移服务器❌ 需重新装✅ 直接拉镜像
手动操作❌ 每次都要✅ 一次搞定
临时目录❌ 只读报错✅ tmpfs 可写
封面图片❌ 写入失败✅ 写入 /tmp

记录我踩过的坑,希望通过这篇教程能帮你省下 5 个小时。🦞