Skip to content

chore: 自行維護 Hermes Docker 映像檔(官方 PR #1523 移除後) #2

Open

Description

@howie

背景

openab PR #1523 移除了官方 Hermes agent 的預建置映像檔支援(Dockerfile.hermes、CI workflow、bake target 等,共 20 檔 −441 行)。官方不再發佈新的 Hermes 映像檔標籤。

官方提供的自行建置指南:https://eli5.openab.dev/howto-build-hermes-openab-image/

核心做法:從 v0.10.0-beta.3 tag 取回 Dockerfile.hermes,自行建置並發佈到自己的 GHCR。

為什麼移除

  • Hermes 的安裝腳本從 raw.githubusercontent.com 抓取,在共用 CI runner 上頻繁回傳 429(rate limit),導致 Docker Smoke Test 失敗
  • 先前加上的重試強化只是遮掩問題
  • 使用率相對維護成本偏低

Hermes 映像檔為什麼這麼大

分析 Dockerfile.hermes(v0.10.0-beta.3)和 Hermes 安裝腳本(install.sh)後,映像檔的膨脹來自以下多層堆疊:

1. 基礎映像:python:3.12-slim-trixie(~150MB 壓縮)

runtime stage 使用 Debian slim,已經是相對精簡的選擇。

2. 系統套件(apt-get install)

ca-certificates curl procps ripgrep tini git ffmpeg unzip xz-utils
  • ffmpeg 是最大的單一套件,安裝後約 100–200MB,僅用於 TTS 語音訊息功能
  • git 也不小(~30MB),但 Hermes 的 skill 同步功能需要它

3. Hermes Agent 本體(install.sh 安裝)

安裝腳本執行以下動作:

  1. 安裝 uv(Rust-based Python 套件管理器)
  2. git clone 整個 hermes-agent repo 到 /usr/local/lib/hermes-agent
  3. 建立 Python venv
  4. uv sync --extra all --locked 安裝完整依賴樹

核心依賴(pyproject.toml dependencies)——每個 session 都用到的:

套件 用途 大小影響
fastapi + uvicorn[standard] Dashboard/API 伺服器 中(含 starlette, uvloop, httptools)
openai LLM provider SDK 中
pydantic 資料驗證 大(含 pydantic-core Rust 擴充)
Pillow 圖片縮放(vision tools) 大(~30MB)
httpx[socks] HTTP client 中
rich 終端格式化 小
websockets CDP browser 控制 小
PyJWT[crypto] Skills Hub JWT 認證 中(含 cryptography)
python-multipart 檔案上傳 小
psutil 程序管理 小
其餘十幾個... 各種功能 累計顯著

[all] extra 額外帶入的:

  • google-api-python-client + 相關套件(Google Workspace skill)
  • mcp + starlette(MCP server)
  • agent-client-protocol(ACP adapter)
  • youtube-transcript-api
  • web extra(fastapi dashboard 完整版)

注意:Hermes 用的是 FastAPI,不是 Flask。 FastAPI 的依賴鏈(starlette + pydantic + uvicorn + uvloop + httptools)同樣不輕量。

4. Node.js runtime(~80–100MB)

安裝腳本會裝 Node.js 22 LTS,用於 browser tools(agent-browser)。在 Docker 映像檔裡這是完整的 Node 二進位 + npm。

5. gh CLI(~30–40MB)

Dockerfile 額外安裝 GitHub CLI,用於 agent 操作 GitHub 的場景。

6. openab Rust binary(~10–20MB)

從 builder stage(rust:1-bookworm)編譯後 COPY 過來,這部分反而是最小的。

估計總映像檔大小

層 估計大小
python:3.12-slim-trixie base ~150MB
apt-get 套件(含 ffmpeg) ~200MB
Hermes agent + Python 依賴([all]) ~400–600MB
Node.js 22 LTS ~80MB
gh CLI ~35MB
openab binary ~15MB
總計(壓縮前) ~900MB – 1.1GB

瘦身方向(未來可探索)

  1. 移除 ffmpeg:如果不需要 TTS 語音功能,這一項就省 100–200MB
  2. 不裝 [all] extra:只裝核心 dependencies,不要 Google/MCP/YouTube 等 extras,按需 lazy-install
  3. 不裝 Node.js:如果不需要 browser tools
  4. 不裝 gh CLI:如果 agent 不需要操作 GitHub
  5. 用 multi-stage 更積極:Python 依賴裝完後清除 pip/uv cache、.git 目錄、__pycache__
  6. 考慮 Alpine base:但 Python wheel 相容性會變差

自行建置的步驟摘要

來源:https://eli5.openab.dev/howto-build-hermes-openab-image/

# 1. 取得 Dockerfile
curl -fsSL https://raw.githubusercontent.com/openabdev/openab/v0.10.0-beta.3/Dockerfile.hermes -o Dockerfile.hermes

# 2. Clone 原始碼(建置 openab 需要)
git clone --depth 1 --branch v0.10.0-beta.3 https://github.com/openabdev/openab.git openab-src
cd openab-src

# 3. 建置
docker build -f ../Dockerfile.hermes -t ghcr.io/<你>/openab-hermes:v0.10.0-beta.3 .

# 4. 推送到 GHCR
docker push ghcr.io/<你>/openab-hermes:v0.10.0-beta.3

也可以用 GitHub Actions 自動化(詳見指南 Chapter 5)。

TODO

  • 確認是否需要自行維護 Hermes 映像檔
  • 如果需要,建立 GitHub Actions workflow 自動建置
  • 評估映像檔瘦身的優先項目(ffmpeg? Node.js? extras?)
  • 測試建置後的映像檔是否正常運作

補充分析:ffmpeg、Node.js/Bun、官方瘦身計畫

ffmpeg 為什麼需要?能不能拿掉?

用途:TTS(文字轉語音)音訊格式轉換。

Hermes 支援多個 TTS provider(edge-tts、ElevenLabs、OpenAI、MiniMax、Mistral Voxtral),回傳的音訊格式各異(mp3, opus, wav, ogg 等),ffmpeg 負責統一轉碼。

結論:如果不用語音功能,可以完全不裝 ffmpeg,省 ~150MB。 TTS 本身是 optional extra(edge-tts 不在核心 dependencies 裡),安裝腳本中 ffmpeg 安裝也不是強制的。

Node.js 能否換成 Bun?

Node.js 在 Hermes 裡有三個用途:

用途 說明 能換 Bun?
agent-browser 瀏覽器自動化工具 可能
Dashboard SPA React/Vite 前端(npm workspace web) 可能
Desktop app Electron 桌面版 不行(Electron 綁 Node)

有趣發現: Hermes issue #93760 揭露 .bun/install cache 在 HERMES_HOME 下佔了 2.5GB(佔 backup 的 82%),代表 agent 子程序已經在透過 Bun 裝套件。

但在 Docker 裡換 Bun 有障礙: monorepo 用 npm workspaces、Desktop 依賴 Electron(硬綁 Node)、agent-browser 相容性未驗證。

更好的做法:如果只需要 ACP adapter(hermes-acp)跑在 openab 裡、不需要 dashboard 和 desktop,可以完全不裝 Node.js。 hermes-acp 是純 Python 入口(acp_adapter.entry:main)。

Hermes 官方有瘦身計畫嗎?

沒有找到任何明確的 Docker image 瘦身 issue 或 roadmap。

但 pyproject.toml 裡有 2026-05-12 的 policy change(Mini Shai-Hulud 供應鏈攻擊事件後):把所有可選後端從 [all] extra 移除,改用 tools/lazy_deps.py 按需安裝。這是 Python 依賴層面的精簡,不是 Docker image 層面。

建議方向:Sidecar 架構

與其打包一個全家桶映像檔,可以拆成最小核心 + sidecar 外掛:

核心容器(~250MB 目標):

  • python:3.12-slim base
  • openab Rust binary
  • hermes-acp(純 Python ACP adapter)
  • Hermes 核心依賴(dependencies 不含 [all] extra)
  • 不裝:ffmpeg、Node.js、gh CLI

Sidecar 容器(按需掛載):

  • TTS sidecar:ffmpeg + edge-tts/elevenlabs
  • Browser sidecar:Node.js + agent-browser
  • Dashboard sidecar:Node.js + React SPA
  • GitHub sidecar:gh CLI(或直接用 API)

這樣核心映像檔可以從 ~1GB 縮到 ~250MB,需要的功能再用 sidecar 加進去。

Activity

  1. howie commented on Sep 12, 2026

    @howie
    OwnerAuthor

    429 修復方案已實作

    分支:worktree-fix-hermes-dockerfile (diff)

    根因

    Dockerfile.hermes 第 34 行 curl -fsSL raw.githubusercontent.com/... 從 GitHub 的 raw file endpoint 抓 install.sh,該端點 unauthenticated rate limit 極低(~60 req/hr/IP),共用 CI runner 的 IP 被多個 org 共用,頻繁 429。

    修法

    完全繞過 raw.githubusercontent.com,改用三段式 multi-stage build:

    1. hermes-deps stage:git clone(走 Git smart HTTP,不同 rate limit pool)+ uv sync
    2. uv binary:從 ghcr.io/astral-sh/uv:latest COPY(官方 container image,走 GHCR CDN)
    3. runtime stage:從 hermes-deps 複製已安裝好的 venv

    額外改進

    • 支援 HERMES_PROFILE build arg:minimal(~250MB)/ full(~900MB)
    • minimal 不裝 ffmpeg / gh CLI,靠 Hermes 的 tools/lazy_deps.py 按需安裝
    • 清除 .git / uv cache / pip / setuptools 縮小映像
    • 保留 uv binary 在 runtime,lazy-install 可用
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions