Clawdbot镜像制作教程:自定义技能打包与快速部署

1. 为什么需要自己制作Clawdbot镜像

Clawdbot(现名Moltbot)作为一款开源自托管的个人AI助手,它的核心魅力在于“本地优先”和“完全可控”。当你在Mac mini或云服务器上运行它时,所有对话记录、操作日志、文件处理都发生在你自己的设备上,数据不会上传到任何第三方服务器。这种设计带来了真正的隐私保障,但也意味着你需要对环境有完整的掌控权。

市面上虽然有预装好的镜像,比如阿里云无影、UCloud提供的Clawdbot一键部署方案,但它们往往只包含基础功能和默认配置。如果你需要接入企业微信、钉钉或QQ等国内主流协作平台,或者想集成OCR识别、财务报销、代码审查等特定业务技能,就必须自己动手定制镜像。

我第一次用官方镜像时就遇到了问题:它默认只支持Telegram和Discord,而我们团队日常用的是企业微信。尝试手动安装插件后发现依赖冲突,折腾了大半天才跑通。后来我才明白,与其在运行中的实例里反复调试,不如从源头开始——把所有需要的技能、配置和依赖都打包进一个专属镜像里。这样每次部署都是干净、一致、可复现的,再也不用担心环境差异带来的各种“玄学问题”。

镜像制作不是为了炫技,而是为了让Clawdbot真正成为你工作流中可靠的一环。就像给汽车换上专为山路调校的轮胎,而不是指望原厂胎能应付所有路况。

2. 准备工作:环境与工具清单

在开始构建镜像前,先确认你的开发环境是否满足基本要求。Clawdbot对Node.js版本有明确要求,低于v22的版本会直接报错,这点很多人容易忽略。

2.1 基础环境检查

打开终端,依次执行以下命令:

# 检查Node.js版本(必须≥22.17.0)
node --version

# 检查npm版本(建议使用pnpm,更轻量)
npm --version

# 如果Node.js版本过低,推荐使用nvm管理多版本
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install 22.17.0
nvm use 22.17.0

2.2 必备工具安装

除了Node.js,还需要几个关键工具来辅助镜像构建和测试:

  • Docker Desktop:用于本地构建和测试镜像(macOS/Windows)或Docker CE(Linux)
  • Git:克隆Clawdbot源码和技能仓库
  • VS Code(推荐):带Remote-Containers插件,可以无缝进入容器开发
  • curl和jq:用于API测试和JSON解析

在macOS上,可以用Homebrew一次性安装:

# 安装Homebrew(如未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 安装必备工具
brew install git docker jq curl

2.3 星图GPU平台准备

本文基于CSDN星图GPU平台进行演示,该平台提供预置的GPU加速环境,特别适合需要运行本地大模型的场景。登录后,选择“GPU计算型”实例,推荐配置为:

  • GPU:NVIDIA A10(24GB显存)
  • CPU:8核
  • 内存:32GB
  • 系统盘:100GB SSD

创建实例后,通过SSH连接,确保能正常执行nvidia-smi命令验证GPU驱动已就绪。这一步很关键,因为很多Clawdbot技能(如图像处理、语音合成)会调用CUDA加速,没有GPU支持会导致功能降级或失败。

3. 技能开发:从零编写第一个自定义Skill

Clawdbot的强大之处在于其Skill系统——你可以把它理解为AI助手的“应用程序”。官方提供了50多个内置Skill,但真正让它融入你工作流的,是你自己编写的那些小而美的功能。

3.1 Skill结构解析

每个Skill本质上是一个独立的Node.js模块,遵循固定目录结构:

my-first-skill/
├── package.json          # 技能元信息
├── index.js              # 主入口文件
├── README.md             # 使用说明
└── assets/               # 静态资源(可选)

以一个简单的“会议纪要生成”Skill为例,它能自动读取你指定的会议录音文件,生成结构化纪要并保存为Markdown。

3.2 编写会议纪要Skill

创建meeting-summary目录,然后编写package.json

{
  "name": "@yourname/meeting-summary",
  "version": "1.0.0",
  "description": "自动生成会议纪要",
  "main": "index.js",
  "keywords": ["meeting", "summary", "transcribe"],
  "dependencies": {
    "ffmpeg-static": "^5.1.0",
    "whisper.cpp": "^1.0.0"
  }
}

接着是核心逻辑index.js

const { exec } = require('child_process');
const fs = require('fs').promises;
const path = require('path');

// Skill注册函数,Clawdbot启动时会调用
module.exports = (clawdbot) => {
  // 定义Skill的命令和描述
  clawdbot.skills.register({
    id: 'meeting-summary',
    name: '会议纪要生成',
    description: '上传会议录音文件,自动生成结构化纪要',
    icon: '',
    // 定义触发方式:当用户说"生成会议纪要"时激活
    triggers: ['生成会议纪要', '总结这个会议'],
    
    // 执行函数,接收用户输入和上下文
    async execute({ input, context }) {
      try {
        // 1. 检查是否有上传的音频文件
        const audioFile = context.files?.find(f => 
          f.type.startsWith('audio/') || f.name.endsWith('.mp3')
        );
        
        if (!audioFile) {
          return '请先上传会议录音文件(MP3/WAV格式)';
        }
        
        // 2. 调用whisper.cpp进行语音转文字
        const transcriptPath = path.join('/tmp', `transcript_${Date.now()}.txt`);
        const whisperCmd = `whisper.cpp/main -m whisper.cpp/models/ggml-base.en.bin -f "${audioFile.path}" -of "${transcriptPath.replace('.txt', '')}"`;
        
        await new Promise((resolve, reject) => {
          exec(whisperCmd, (error, stdout, stderr) => {
            if (error) reject(error);
            else resolve();
          });
        });
        
        // 3. 读取转录文本并用大模型生成纪要
        const transcript = await fs.readFile(`${transcriptPath}.txt`, 'utf8');
        const summary = await clawdbot.llm.chat({
          messages: [
            { role: 'system', content: '你是一位专业的会议秘书,请根据以下会议录音内容,生成结构化纪要,包含:1. 会议主题 2. 参会人员 3. 主要议题 4. 行动项(负责人+截止时间)' },
            { role: 'user', content: transcript.substring(0, 4000) } // 限制长度防超限
          ]
        });
        
        // 4. 保存纪要为Markdown文件
        const summaryPath = path.join(context.workspace, `会议纪要_${Date.now()}.md`);
        await fs.writeFile(summaryPath, summary.content);
        
        return ` 会议纪要已生成!\n\n${summary.content}\n\n文件已保存至:${summaryPath}`;
      } catch (error) {
        console.error('会议纪要生成失败:', error);
        return ` 处理失败:${error.message}`;
      }
    }
  });
};

这个Skill展示了Clawdbot Skill开发的核心模式:接收用户输入→处理文件→调用模型→返回结果。它没有复杂的前端界面,所有交互都通过自然语言完成,这才是AI助手该有的样子。

3.3 技能测试与调试

在本地测试Skill,无需启动完整Clawdbot服务。创建一个简单的测试脚本test-skill.js

// 加载Clawdbot核心模块(需先npm install @clawdbot/core)
const { Clawdbot } = require('@clawdbot/core');

async function testSkill() {
  const bot = new Clawdbot();
  
  // 手动注册Skill
  await import('./meeting-summary/index.js').then(module => {
    module.default(bot);
  });
  
  // 模拟用户输入
  const result = await bot.skills.execute('meeting-summary', {
    input: '生成会议纪要',
    context: {
      files: [{ path: '/path/to/test.mp3', name: 'demo.mp3', type: 'audio/mpeg' }],
      workspace: '/tmp'
    }
  });
  
  console.log('测试结果:', result);
}

testSkill();

运行node test-skill.js,观察输出是否符合预期。调试阶段重点关注三点:文件路径是否正确、依赖是否安装成功、大模型调用是否返回合理内容。

4. 依赖打包:解决环境一致性难题

Clawdbot技能开发中最让人头疼的不是写代码,而是环境依赖。比如上面的会议纪要Skill需要whisper.cpp二进制文件,而它在不同CPU架构(x86_64 vs ARM64)和操作系统(Linux vs macOS)上的编译产物完全不同。如果直接在星图平台上安装,很可能遇到“本地能跑,线上报错”的情况。

4.1 依赖分类与处理策略

Clawdbot的依赖可分为三类,每种需要不同的打包策略:

依赖类型 示例 打包策略 说明
纯JavaScript依赖 axios, lodash npm install 直接写入package-lock.json,Docker构建时自动安装
二进制可执行文件 whisper.cpp, ffmpeg 预编译+COPY 在目标平台(星图GPU)上编译,COPY到镜像中
系统级依赖 libasound2, libx11 apt-get install 在Dockerfile中用系统包管理器安装

4.2 预编译whisper.cpp

由于星图平台使用Ubuntu 22.04 + NVIDIA A10 GPU,我们需要在这个环境中预编译whisper.cpp

# 在星图GPU实例中执行
git clone https://github.com/ggerganov/whisper.cpp.git
cd whisper.cpp
make clean && make -j$(nproc)

# 下载预训练模型(base.en,约150MB)
./models/download-ggml-model.sh base.en

# 验证编译结果
./main -h

编译完成后,将整个whisper.cpp目录打包:

tar -czf whisper-cpp-ubuntu22.tar.gz whisper.cpp/

然后在本地开发机上,把这个压缩包放入项目目录,后续Docker构建时会解压使用。

4.3 构建最小化Dockerfile

基于Clawdbot官方Docker镜像,我们构建一个精简版Dockerfile:

# 使用官方Clawdbot基础镜像(已预装Node.js 22+)
FROM clawdbot/clawdbot:latest

# 设置工作目录
WORKDIR /app

# 复制预编译的whisper.cpp
COPY whisper-cpp-ubuntu22.tar.gz .
RUN tar -xzf whisper-cpp-ubuntu22.tar.gz && \
    rm whisper-cpp-ubuntu22.tar.gz

# 复制自定义Skill
COPY meeting-summary ./skills/meeting-summary

# 安装系统依赖(whisper.cpp需要)
RUN apt-get update && apt-get install -y \
    libasound2 \
    libx11-6 \
    && rm -rf /var/lib/apt/lists/*

# 安装Node.js依赖
COPY package.json .
RUN npm ci --only=production

# 复制应用代码
COPY . .

# 创建符号链接,让Clawdbot能自动发现Skill
RUN ln -sf /app/skills/meeting-summary /app/node_modules/@yourname/meeting-summary

# 暴露端口
EXPOSE 18789

# 启动命令
CMD ["npm", "start"]

这个Dockerfile的关键点在于:不重新编译任何二进制文件,所有复杂依赖都在构建前准备好;使用npm ci而非npm install,确保依赖版本与package-lock.json完全一致;通过符号链接方式注册Skill,避免修改Clawdbot核心代码。

5. 镜像构建与部署全流程

现在到了最关键的一步:把代码、依赖、配置打包成一个可部署的镜像。整个过程分为本地构建验证和星图平台部署两个阶段。

5.1 本地构建与测试

在项目根目录执行:

# 构建镜像(注意最后的点,表示当前目录)
docker build -t my-clawdbot:latest .

# 运行容器进行测试
docker run -p 18789:18789 -it my-clawdbot:latest

# 浏览器访问 http://localhost:18789 查看Web UI

首次构建可能需要10-15分钟,主要耗时在下载基础镜像和安装依赖。构建成功后,你会看到Clawdbot启动日志,最后出现Gateway started on port 18789表示服务已就绪。

在Web UI中,输入/skills list命令,应该能看到meeting-summary技能已注册。上传一个MP3文件并发送“生成会议纪要”,观察是否能正确生成纪要。

5.2 推送至星图镜像仓库

星图GPU平台支持私有镜像仓库,登录后获取你的命名空间(如csdn-user),然后推送:

# 登录星图镜像仓库(按提示输入账号密码)
docker login registry.csdn.net

# 重新打标签
docker tag my-clawdbot:latest registry.csdn.net/csdn-user/my-clawdbot:1.0.0

# 推送
docker push registry.csdn.net/csdn-user/my-clawdbot:1.0.0

推送过程会显示实时进度,1.0.0版本约500MB,取决于你的Skill大小。网络稳定情况下,5-10分钟可完成。

5.3 星图平台一键部署

登录CSDN星图GPU控制台,进入“镜像市场” → “我的镜像”,找到刚推送的my-clawdbot:1.0.0,点击“部署”。

在部署配置页面:

  • 实例名称:填入clawdbot-meeting-assistant
  • GPU规格:保持A10(会议纪要需要GPU加速)
  • 环境变量:添加CLAWDBOT_MODEL_PROVIDER=ollama(如果使用本地Ollama模型)
  • 启动命令:留空(使用Dockerfile中定义的CMD)

点击“立即部署”,平台会自动拉取镜像、创建容器、分配公网IP。大约2分钟后,状态变为“运行中”,点击“访问应用”即可打开Web UI。

5.4 企业微信通道配置

部署完成后,需要配置企业微信作为消息入口。这步不需要修改镜像,而是通过Clawdbot的动态配置能力完成:

# 进入容器执行配置命令
docker exec -it <container-id> bash

# 安装企业微信插件
clawdbot plugins install @william.qian/simple-wecom

# 启用插件
clawdbot plugins enable simple-wecom

# 配置企业微信参数(从企微后台获取)
clawdbot config set channels.simple-wecom.corpid "ww1234567890abcdef"
clawdbot config set channels.simple-wecom.corpsecret "your-secret"
clawdbot config set channels.simple-wecom.token "your-token"
clawdbot config set channels.simple-wecom.encodingAESKey "your-aes-key"

# 重启网关使配置生效
clawdbot gateway restart

配置完成后,在企业微信管理后台的“应用管理”中,找到你创建的Clawdbot应用,将其添加到测试部门。成员在企微中@机器人发送“生成会议纪要”,就能触发刚刚编写的Skill。

6. 实战优化:提升生产环境稳定性

镜像部署成功只是第一步,要让它在生产环境中长期稳定运行,还需要几个关键优化。

6.1 日志与监控配置

默认情况下,Clawdbot日志输出到控制台,不利于问题排查。我们在Dockerfile中添加日志轮转:

# 在Dockerfile末尾添加
RUN npm install -g pm2 && \
    mkdir -p /app/logs

# 修改启动命令,使用pm2管理进程
CMD ["pm2-runtime", "start", "ecosystem.config.js"]

创建ecosystem.config.js

module.exports = {
  apps: [{
    name: 'clawdbot',
    script: './node_modules/.bin/clawdbot',
    args: 'start',
    instances: 1,
    autorestart: true,
    watch: false,
    max_memory_restart: '1G',
    env: {
      NODE_ENV: 'production',
      PORT: 18789
    },
    log_file: '/app/logs/clawdbot-out.log',
    error_file: '/app/logs/clawdbot-error.log',
    out_file: '/app/logs/clawdbot-combined.log',
    time: true
  }]
};

这样配置后,所有日志会自动写入/app/logs/目录,并按日期轮转,避免磁盘被占满。

6.2 安全加固措施

Clawdbot拥有系统级权限,安全不容忽视。在星图平台部署时,务必启用以下设置:

  • 网络隔离:将实例放入私有子网,仅开放18789端口给企业微信服务器IP段(企微文档提供白名单)
  • 防火墙规则:在安全组中限制SSH访问,只允许公司办公网络IP
  • 定期备份:配置自动快照,每天凌晨2点备份系统盘,保留7天

更重要的是,禁用不必要的Skill。在config.json中明确指定启用的Skill:

{
  "skills": {
    "enabled": [
      "meeting-summary",
      "file-manager",
      "web-search"
    ],
    "disabled": [
      "shell-exec",  // 生产环境禁用直接执行shell命令
      "browser-control"
    ]
  }
}

这样即使某个Skill存在漏洞,攻击面也被严格限制。

6.3 故障自愈机制

为应对意外崩溃,我们在容器启动时添加健康检查:

# 在Dockerfile中添加
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:18789/api/health || exit 1

同时,在星图平台的实例设置中,启用“自动恢复”选项。当健康检查连续3次失败时,平台会自动重启容器,确保服务可用性。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐