收起左侧

Hermes Agent 三合一 Docker 部署指南

0
回复
25
查看
[ 复制链接 ]

10

主题

62

回帖

0

牛值

初出茅庐

fnOS1.0上线纪念勋章

Hermes Agent 三合一 Docker 部署指南

这是什么

Hermes Agent 是一个 AI 代理框架,官方推荐用三个容器分别跑网关、监控面板和聊天界面。这篇文章记录我怎么把它们跑起来的,踩了哪些坑,以及最终的配置方案。

为什么需要三个容器

简单说就是职责分离:

  • hermes — 网关 API,处理所有请求,端口 8642
  • dashboard — 监控面板,看运行状态和会话,端口 9119
  • webui — 浏览器聊天界面,端口 8787

三个容器共享同一份数据(配置、会话、记忆、技能),靠挂载同一个目录实现。

踩坑记录

坑 1:端**露

默认端口直接映射到 0.0.0.0,意味着外网可以直接访问。生产环境必须加防火墙或者反向代理。

坑 2:权限问题

三个容器默认用户可能不一样,导致同一个挂载目录互相读写报 Permission denied。解决方法是给三个容器统一指定 user: "1000:1000",同时把宿主机目录 owner 设为 1000:1000,权限 755。

坑 3:WebUI 需要 agent 源码

WebUI 启动时会检查 agent 源码目录,没有的话功能受限。源码在 agent 容器的 /opt/hermes 里,需要复制到宿主机再挂载给 webui。

坑 4:webui 的 HERMES_HOME

agent 和 dashboard 设置了 HERMES_HOME=/opt/data,但 webui 没有设置这个变量,导致它读不到 config.yaml,报 "No LLM provider configured"。加一行 HERMES_HOME=/home/hermeswebui/.hermes 就解决了。

坑 5:配置变更不会自动生效

在 agent 里通过 hermes setup 配置了模型,webui 不会自动感知,需要重启 webui 容器。

最终配置

目录结构

project/
**── docker-compose.yml
**── init.sh              # 从镜像复制 agent 源码,只需跑一次
**── hermes/
    **── data/            # 配置、会话、记忆、skills
    **── hermes/          # agent 源码(init.sh 自动复制)

docker-compose.yml

services:
  hermes:
    image: nousresearch/hermes-agent:latest
    container_name: hermes
    restart: unless-stopped
    command: gateway run
    user: "1000:1000"
    ports:
      - "8642:8642"
    volumes:
      - ./hermes/data:/opt/data
    environment:
      # - GATEWAY_ALLOW_ALL_USERS=true  #(实测关闭没有问题)
      - TZ=Asia/Shanghai
    networks:
      - hermes-net

  dashboard:
    image: nousresearch/hermes-agent:latest
    container_name: hermes-dashboard
    restart: unless-stopped
    command: dashboard --host 0.0.0.0 --insecure
    user: "1000:1000"
    ports:
      - "9119:9119"
    volumes:
      - ./hermes/data:/opt/data
    environment:
      - GATEWAY_HEALTH_URL=http://hermes:8642
      - TZ=Asia/Shanghai
    networks:
      - hermes-net
    depends_on:
      - hermes

  webui:
    image: ghcr.io/nesquena/hermes-webui:latest
    container_name: hermes-webui
    restart: unless-stopped
    ports:
      - "8787:8787"
    volumes:
      - ./hermes/data:/home/hermeswebui/.hermes
      - ./hermes/hermes:/home/hermeswebui/.hermes/hermes-agent
      - ./hermes/data/workspace:/workspace
    environment:
      - HERMES_HOME=/home/hermeswebui/.hermes
      - HERMES_WEBUI_HOST=0.0.0.0
      - HERMES_WEBUI_PORT=8787
      - HERMES_WEBUI_STATE_DIR=/home/hermeswebui/.hermes/webui
      - TZ=Asia/Shanghai
      - WANTED_UID=1000
      - WANTED_GID=1000
      # - HERMES_WEBUI_PASSWORD=your-password
    networks:
      - hermes-net
    depends_on:
      - hermes

networks:
  hermes-net:
    driver: bridge

init.sh

#!/bin/bash
set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
DEST="$SCRIPT_DIR/hermes/hermes"
DATA="$SCRIPT_DIR/hermes/data"
IMAGE="nousresearch/hermes-agent:latest"

mkdir -p "$DATA"
mkdir -p "$DEST"

# 统一 UID 1000:1000,三个容器都用同一个用户
sudo chown -R 1000:1000 "$DATA"
sudo chmod -R 755 "$DATA"

if [ -f "$DEST/pyproject.toml" ]; then
    echo "Source already exists at $DEST"
else
    echo "Copying agent source from $IMAGE ..."
    docker run --rm \
        --entrypoint sh \
        -v "$DEST:/dest" \
        "$IMAGE" \
        -c 'cd /opt/hermes && tar \
            --exclude=.venv \
            --exclude=.playwright \
            --exclude=node_modules \
            --exclude=package.json \
            --exclude=package-lock.json \
            --exclude=__pycache__ \
            --exclude=hermes_agent.egg-info \
            --exclude=.git \
            --exclude=tests \
            --exclude=docs \
            --exclude=website \
            -cf - . | (cd /dest && tar xf -)'
    echo "Done. Source copied to $DEST"
fi

sudo chown -R 1000:1000 "$DEST"
sudo chmod -R 755 "$DEST"

echo ""
echo "Ready. Run: docker compose up -d"

部署步骤

chmod +x init.sh
./init.sh
docker compose up -d

三条命令,完事。

访问地址:

  • http://localhost:8642 — Gateway API
  • http://localhost:9119 — Dashboard
  • http://localhost:8787 — WebUI

配置模型

docker exec hermes hermes setup

按提示选 provider,填 API key。配完后重启 webui:

docker compose restart webui

可能遇到的问题

1. init.sh 报 Permission denied

需要 sudo 权限。如果不想用 sudo,手动 chown 也行。

2. webui 报 "No LLM provider configured"

确认 config.yaml 里有 providers 配置,然后 docker compose restart webui

3. skills 同步报 "File exists"

无害。两个容器都会往 skills 目录写入,第二次启动时文件已存在就跳过了。

4. 上游镜像更新了

拉最新镜像重新启动:

docker compose pull
docker compose up -d

源码如果也需要更新,删掉 ./hermes/hermes/ 然后重新跑 init.sh

5. 迁移

整个目录打包带走:

tar czf hermes.tar.gz hermes/ docker-compose.yml init.sh

目标机器解压后 docker compose up -d 就行。

为什么不用命名卷

命名卷迁移时需要 docker volume 操作,不直观。绑定挂载就是普通目录,打包复制就行,对运维更友好。代价是需要手动处理权限,但 init.sh 已经帮你搞定了。

已知问题

问题 风险
端**露 0.0.0.0 外网直接访问,无防火墙(自行修改配置)
无 webui 密码 任何人能进聊天界面(自行修改配置)
SQLite 并发写 两个容器同时写 state.db 可能损坏
skills 目录冲突 两个容器都往 skills 写入
无健康检查 依赖服务没就绪就启动
源码只复制一次 镜像更新后代码过时(删除源码目录重新初始化)
收藏
送赞 1
分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则