Docker部署Hermes Agent的踩坑與最佳實(shí)踐
為什么選擇 Docker 部署
Hermes Agent 依賴 Python 虛擬環(huán)境、Node.js 運(yùn)行時(shí)、Playwright 瀏覽器以及大量系統(tǒng)級工具(ffmpeg、pandoc、ripgrep 等)。直接裸機(jī)安裝會導(dǎo)致:
- 依賴沖突:多個(gè)項(xiàng)目共用 Python/Node 版本時(shí)容易出錯(cuò)
- 難以遷移:換服務(wù)器需要重新配置所有環(huán)境
- 權(quán)限混亂:不同服務(wù)以不同用戶運(yùn)行,文件屬主不一致
Docker 部署的核心優(yōu)勢:
| 優(yōu)勢 | 說明 |
|---|---|
| 環(huán)境隔離 | 所有依賴封裝在鏡像內(nèi),不污染宿主機(jī) |
| 可復(fù)現(xiàn) | 鏡像 SHA256 校驗(yàn),每次構(gòu)建結(jié)果一致 |
| 數(shù)據(jù)分離 | 用戶數(shù)據(jù)掛載在 /opt/data volume,與代碼層完全解耦 |
| 權(quán)限可控 | 運(yùn)行時(shí)以非 root 用戶執(zhí)行,最小化攻擊面 |
核心架構(gòu)設(shè)計(jì)
目錄職責(zé)劃分
Hermes Agent 的目錄設(shè)計(jì)是整個(gè)部署方案的核心:
# 代碼層(鏡像內(nèi),只讀) /opt/hermes/ # 代碼、venv、node_modules /opt/hermes/.venv/ # Python 虛擬環(huán)境 /opt/hermes/bin/ # 可執(zhí)行文件 # 數(shù)據(jù)層(Volume 掛載,持久化) /opt/data/ # 用戶數(shù)據(jù)、配置、sessions、skills /opt/data/.local/bin # agent 安裝的 npm/pip 工具
關(guān)鍵設(shè)計(jì):容器內(nèi) $HOME 設(shè)為 /opt/data,npm prefix(~/.local)自然落在持久化路徑內(nèi),工具不會因重啟而丟失。
ENV HERMES_HOME=/opt/data
ENV PATH="/opt/hermes/bin:/opt/hermes/.venv/bin:/opt/data/.local/bin:${PATH}"
VOLUME [ "/opt/data" ]
進(jìn)程監(jiān)督:s6-overlay
鏡像使用 s6-overlay 作為 PID 1,替代早期的 tini:
- 僵尸進(jìn)程回收:s6-svscan 在 SIGCHLD 時(shí)非阻塞回收孤兒進(jìn)程
- 服務(wù)監(jiān)督:main-hermes、dashboard、per-profile gateway 均受監(jiān)督,崩潰自動(dòng)重啟
- 啟動(dòng)順序保證:cont-init.d 腳本按字典序執(zhí)行,權(quán)限修復(fù)在服務(wù)啟動(dòng)前完成
非 root 運(yùn)行
RUN useradd -u 10000 -m -d /opt/data hermes
每個(gè)監(jiān)督服務(wù)通過 s6-setuidgid hermes 降權(quán)運(yùn)行。docker exec 默認(rèn)以 root 進(jìn)入容器——為此提供了 /opt/hermes/bin/hermes shim,自動(dòng)轉(zhuǎn)發(fā)給 s6-setuidgid hermes 執(zhí)行,避免寫出 root 屬主文件導(dǎo)致運(yùn)行時(shí) EACCES。
對官方 Dockerfile 的修改
1. 鏡像源全面國內(nèi)化
問題:官方鏡像從 Docker Hub、deb.debian.org、npmjs.org、pypi.org 拉取,在國內(nèi)構(gòu)建速度極慢甚至超時(shí)。
解決方案:
# Node 基礎(chǔ)鏡像:官方 → DaoCloud 鏡像 - FROM node:22-bookworm-slim AS node_source + FROM docker.m.daocloud.io/library/node:22-bookworm-slim AS node_source # apt 源:deb.debian.org → 中科大鏡像 + RUN sed -i 's|deb.debian.org|mirrors.ustc.edu.cn|g' /etc/apt/sources.list.d/debian.sources # npm registry → npmmirror + ENV npm_config_registry=https://registry.npmmirror.com # 比 npm config set 更早生效,構(gòu)建階段也生效 # PyPI → 清華鏡像 + RUN uv sync ... --index-url https://pypi.tuna.tsinghua.edu.cn/simple/
2. 新增系統(tǒng)工具包
問題:官方鏡像為精簡體積裁掉了部分工具,我們的使用場景需要它們。
+ wget # 部分腳本依賴 wget 而非 curl + file jq # 文件類型檢測、JSON 處理 + librsvg2-bin # SVG 轉(zhuǎn)換(cairosvg 的系統(tǒng)依賴) + pandoc # 文檔格式轉(zhuǎn)換 + g++ make cmake # v0.17.0 Matrix gateway 依賴的原生編譯工具 + fonts-noto-cjk fonts-noto-cjk-extra # 中文字體
3. 新增 Python 包
RUN uv pip install --no-cache-dir \
--index-url https://pypi.tuna.tsinghua.edu.cn/simple/ \
feedparser markdown whoosh \ # RSS 解析、Markdown 渲染、全文搜索
Pillow numpy jieba \ # 圖像處理、數(shù)值計(jì)算、中文分詞
duckduckgo-search websocket-client \ # 搜索、WebSocket 通信
cairosvg soundfile weasyprint \ # SVG/音頻/HTML→PDF 轉(zhuǎn)換
wordcloud tiktoken pyarrow \ # 詞云、token 計(jì)數(shù)、列式存儲
pytest litellm \ # 測試框架、多模型 LLM 接口
rtk-hermes # RTK Hermes 集成
4. rtk 固定版本(構(gòu)建可復(fù)現(xiàn))
ARG RTK_VERSION=0.42.4
RUN curl -fsSLk ... "https://github.com/rtk-ai/rtk/releases/download/v${RTK_VERSION}/rtk-..."
不固定版本會在每次 docker build 時(shí)拉取最新 release,導(dǎo)致不同時(shí)間構(gòu)建的鏡像行為差異。ARG 固定后可通過 --build-arg RTK_VERSION=x.y.z 按需升級。
5. s6-overlay 下載方式優(yōu)化
問題:官方用 curl 在 RUN 步驟內(nèi)下載 s6-overlay,每次構(gòu)建都重新下載。
解決方案:改用 ADD 指令,BuildKit 會將 tarball 緩存在層中,僅 URL 變化時(shí)才重新拉取。
# 改為 ADD,利用 BuildKit 緩存 + ADD https://github.com/.../s6-overlay-x86_64.tar.xz /tmp/s6-overlay-x86_64.tar.xz + ADD https://github.com/.../s6-overlay-aarch64.tar.xz /tmp/s6-overlay-aarch64.tar.xz - curl -fsSL --retry 3 -o /tmp/s6-overlay-arch.tar.xz "..."
構(gòu)建鏡像
Dockerfile 修改完成后,先構(gòu)建鏡像再啟動(dòng)容器:
# 進(jìn)入 Dockerfile 所在目錄 cd /path/to/hermes-agent # 構(gòu)建鏡像(首次約 10-15 分鐘,后續(xù)有緩存會快很多) docker build -t hermes-agent:v2026.6.19 . # 驗(yàn)證鏡像構(gòu)建成功 docker images | grep hermes-agent # 期望輸出:hermes-agent v2026.6.19 <image_id> <size>
構(gòu)建參數(shù)說明:
| 參數(shù) | 說明 |
|---|---|
-t hermes-agent:v2026.6.19 | 鏡像名稱和標(biāo)簽,后續(xù) docker run / compose.yml 中引用的就是這個(gè)名字 |
. | 構(gòu)建上下文為當(dāng)前目錄(包含 Dockerfile) |
自定義 rtk 版本(可選):
docker build --build-arg RTK_VERSION=0.42.4 -t hermes-agent:v2026.6.19 .
國內(nèi)構(gòu)建加速提示:Dockerfile 已切換國內(nèi)鏡像源(apt/npm/PyPI),無需額外配置代理。如果 docker build 本身拉取基礎(chǔ)鏡像慢,可配置 Docker daemon 的 registry-mirrors。
部署步驟
1. 啟動(dòng)容器
方式一:docker run
docker run -d \
--name hermes \
--restart unless-stopped \
-p 127.0.0.1:9119:9119 \
-v ~/.hermes:/opt/data \
-e TZ=Asia/Shanghai \
-e HERMES_DASHBOARD=true \
-e HERMES_DASHBOARD_INSECURE=true \
hermes-agent:v2026.6.19 gateway run
方式二:docker compose(推薦)
compose.yml:
services:
hermes:
image: hermes-agent:v2026.6.19
container_name: hermes
restart: unless-stopped
ports:
- "127.0.0.1:9119:9119"
volumes:
- ~/.hermes:/opt/data
environment:
- HERMES_UID=${HERMES_UID:-10000}
- HERMES_GID=${HERMES_GID:-10000}
- TZ=Asia/Shanghai
- HERMES_DASHBOARD=true
- HERMES_DASHBOARD_INSECURE=true
command: ["gateway", "run"]啟動(dòng):
docker compose up -d
9119 端口綁定 127.0.0.1,僅本機(jī)訪問。如需遠(yuǎn)程訪問,通過 SSH 隧道或反向代理轉(zhuǎn)發(fā),不要直接綁定 0.0.0.0。
2. 驗(yàn)證運(yùn)行狀態(tài)
# 查看啟動(dòng)日志 docker logs hermes -f # 查看 stage2-hook 初始化輸出 docker logs hermes 2>&1 | grep '\[stage2\]' # 進(jìn)入容器調(diào)試(自動(dòng)以 hermes 用戶執(zhí)行) docker exec hermes hermes status
踩坑記錄
坑 1:不要用--user啟動(dòng)容器
現(xiàn)象:docker run --user $(id -u):$(id -g) 啟動(dòng)后容器直接報(bào)錯(cuò)退出。
原因:s6-overlay 的 cont-init.d 階段需要 root 權(quán)限執(zhí)行 UID remap、chown 等操作。非 root 啟動(dòng)時(shí)這些步驟全部跳過,hermes 代碼樹(UID 10000)對任意其他 UID 均不可寫,必然 EACCES 崩潰。
正確做法:以 root 啟動(dòng)(默認(rèn)),通過 HERMES_UID / PUID 環(huán)境變量傳入宿主機(jī) UID。
坑 2:工具重啟后消失(npm/pip 包丟失)
現(xiàn)象:在 Hermes 內(nèi)安裝了飛書 CLI、某個(gè) npm 工具,重啟容器后全部找不到。
原因:若未正確配置 $HOME,npm prefix 默認(rèn)落在 ~/.local(容器內(nèi)非持久路徑),重啟后鏡像層重置,安裝記錄清空。
本項(xiàng)目的解法:HERMES_HOME=/opt/data 已將 $HOME 指向持久化 volume,~/.local 解析為 /opt/data/.local,PATH 也已包含 /opt/data/.local/bin。只要工具安裝到 $HOME 路徑下,重啟后自動(dòng)恢復(fù)。
坑 3:docker exec寫出 root 屬主文件
現(xiàn)象:docker exec <container> hermes ... 執(zhí)行后,/opt/data 下出現(xiàn) root 屬主文件,下次啟動(dòng) gateway 報(bào) PermissionError。
解法一(推薦):鏡像內(nèi)置了 /opt/hermes/bin/hermes shim,它檢測到 root 調(diào)用時(shí)自動(dòng) s6-setuidgid hermes 降權(quán),直接 docker exec hermes hermes ... 即可安全使用。
解法二:顯式指定用戶 docker exec -u hermes hermes ...。
坑 4:Docker 鏡像拉取被攔截,可以切換國內(nèi)鏡像
現(xiàn)象:docker pull 超時(shí)或報(bào) connection refused。
解法:Dockerfile 已切換到國內(nèi)鏡像源:
- Debian apt 源 →
mirrors.ustc.edu.cn - npm registry →
registry.npmmirror.com - PyPI →
pypi.tuna.tsinghua.edu.cn - Node 基礎(chǔ)鏡像 →
docker.m.daocloud.io/library/node:22-bookworm-slim
坑 5:UID 重映射后 .venv / ui-tui 權(quán)限錯(cuò)誤
現(xiàn)象:指定 HERMES_UID 后,lazy install(discord.py、telegram 等適配器)失敗,TUI 每次重新編譯 dist/entry.js。
原因:usermod -u <new> hermes 會重新 chown $HOME(/opt/data),但不會動(dòng) /opt/hermes/.venv、/opt/hermes/ui-tui 等構(gòu)建產(chǎn)物,它們?nèi)詫僦?10000,新 UID 無法寫入。
解法:stage2-hook.sh 在每次啟動(dòng)時(shí)檢測 venv 屬主,若與運(yùn)行時(shí) UID 不一致則執(zhí)行一次 chown -R:
venv_owner=$(stat -c %u "$INSTALL_DIR/.venv")
if [ "$venv_owner" != "$actual_hermes_uid" ]; then
chown -R hermes:hermes "$INSTALL_DIR/.venv" "$INSTALL_DIR/ui-tui" ...
fi
安全注意事項(xiàng)
- 不要暴露 6789/6790 端口到公網(wǎng):Web UI 和 Gateway 默認(rèn)無認(rèn)證,應(yīng)通過反向代理(nginx/caddy)加 HTTPS + BasicAuth 后再對外。
- API Key 保存在
/opt/data/.env:文件權(quán)限為600,僅 hermes 用戶可讀,不要將其納入 git。 - 鏡像完整性校驗(yàn):s6-overlay tarball 在構(gòu)建時(shí)通過 SHA256 校驗(yàn),防止供應(yīng)鏈攻擊。
總結(jié)
Docker 部署 Hermes Agent 的核心要點(diǎn):
- 目錄分離:代碼層只讀,數(shù)據(jù)層持久化
- 權(quán)限管理:s6-overlay + hermes 用戶降權(quán)
- 國內(nèi)優(yōu)化:鏡像源全面切換到國內(nèi)鏡像
- 工具持久化:
HERMES_HOME=/opt/data確保 npm/pip 工具不丟失
按照本文檔操作,應(yīng)該能夠順利部署并運(yùn)行 Hermes Agent。如有問題,歡迎在評論區(qū)交流。
以上就是Docker部署Hermes Agent的踩坑與最佳實(shí)踐的詳細(xì)內(nèi)容,更多關(guān)于Docker部署Hermes Agent的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
本文給大家介紹在Docker中部署Hermes Agent的方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2026-05-19
Hermes Agent Windows Docker 部署完全指南如何從零開始搭建你的自我進(jìn)化AI 智能體
HermesAgent是NousResearch開發(fā)的開源自我進(jìn)化型AI智能體,支持多模型、多平臺網(wǎng)關(guān)和持久化記憶,文章詳細(xì)介紹了環(huán)境準(zhǔn)備、Docker鏡像拉取、初始化配置、接入LLM模型、啟動(dòng)運(yùn)2026-05-13



