Hermes Agent — Docker
Docker 与 Hermes Agent 有两种不同的结合方式:
- 在 Docker 中运行 Hermes——agent 本身在容器内运行(本页主要关注此方式)
- Docker 作为终端后端——agent 在主机上运行,但每条命令都在单个持久的 Docker 沙箱容器内执行,该容器在 Hermes 进程的生命周期内跨工具调用、
/new和子 agent 持续存在(请参阅配置 → Docker 后端)
本页介绍方式 1。该容器将所有用户数据(配置、API 密钥、会话、技能、记忆)存储在从主机挂载到 /opt/data 的单个目录中。镜像本身是无状态的,可以通过拉取新版本进行升级,而不会丢失任何配置。
快速开始
如果这是你第一次运行 Hermes Agent,请在主机上创建一个数据目录并以交互方式启动容器以运行设置向导:
mkdir -p ~/.hermes
docker run -it --rm \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent setup这会进入设置向导,提示你输入 API 密钥并将其写入 ~/.hermes/.env。你只需执行此操作一次。强烈建议在此步骤中设置一个供网关使用的聊天系统。
以网关模式运行
配置完成后,以后台持久网关(Telegram、Discord、Slack、WhatsApp 等)方式运行容器:
docker run -d \
--name hermes \
--restart unless-stopped \
-v ~/.hermes:/opt/data \
-p 8642:8642 \
nousresearch/hermes-agent gateway run端口 8642 暴露网关的 OpenAI 兼容 API 服务器和健康检查端点。如果仅使用聊天平台(Telegram、Discord 等),这是可选的;但如果需要仪表盘或外部工具访问网关,则是必需的。
注意:API 服务器由 API_SERVER_ENABLED=true 控制。要将其暴露到容器内的 127.0.0.1 之外,还需设置 API_SERVER_HOST=0.0.0.0 和一个 API_SERVER_KEY(最少 8 个字符——使用 openssl rand -hex 32 生成)。示例:
docker run -d \
--name hermes \
--restart unless-stopped \
-v ~/.hermes:/opt/data \
-p 8642:8642 \
-e API_SERVER_ENABLED=true \
-e API_SERVER_HOST=0.0.0.0 \
-e API_SERVER_KEY=your_api_key_here \
-e API_SERVER_CORS_ORIGINS='*' \
nousresearch/hermes-agent gateway run在面向互联网的机器上开放任何端口都存在安全风险。除非你了解相关风险,否则不应这样做。
运行仪表盘
内置的 Web 仪表盘作为可选副进程在网关所在的同一容器中运行。设置 HERMES_DASHBOARD=1 并暴露端口 9119 以及网关的 8642:
docker run -d \
--name hermes \
--restart unless-stopped \
-v ~/.hermes:/opt/data \
-p 8642:8642 \
-p 9119:9119 \
-e HERMES_DASHBOARD=1 \
nousresearch/hermes-agent gateway run入口点在 exec 主命令之前以后台方式启动 hermes dashboard(以非 root 的 hermes 用户身份运行)。仪表盘输出在 docker logs 中以 [dashboard] 为前缀,便于与网关日志区分。
| 环境变量 | 说明 | 默认值 |
|---|---|---|
HERMES_DASHBOARD | 设置为 1(或 true / yes)以在主命令旁启动仪表盘 | (未设置——仪表盘不启动) |
HERMES_DASHBOARD_HOST | 仪表盘 HTTP 服务器的绑定地址 | 0.0.0.0 |
HERMES_DASHBOARD_PORT | 仪表盘 HTTP 服务器的端口 | 9119 |
HERMES_DASHBOARD_TUI | 设置为 1 以暴露浏览器内聊天标签页(通过 PTY/WebSocket 嵌入的 hermes --tui) | (未设置) |
默认的 HERMES_DASHBOARD_HOST=0.0.0.0 是必需的,以便主机通过已发布的端口访问仪表盘;入口点在这种情况下会自动向 hermes dashboard 传递 --insecure。如果要限制仪表盘仅限容器内访问(例如在 sidecar 的反向代理后面),请覆盖为 127.0.0.1。
:::note 仪表盘副进程不受监督——如果崩溃,它将保持关闭状态,直到容器重启。不支持将其作为单独容器运行:仪表盘的网关存活检测需要与网关进程共享 PID 命名空间。 :::
以交互方式运行(CLI 聊天)
要针对正在运行的数据目录打开交互式聊天会话:
docker run -it --rm \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent或者,如果你已通过 Docker Desktop 等方式在运行的容器中打开了终端,只需运行:
/opt/hermes/.venv/bin/hermes持久卷
/opt/data 卷是所有 Hermes 状态的唯一真实来源。它映射到主机的 ~/.hermes/ 目录,包含:
| 路径 | 内容 |
|---|---|
.env | API 密钥和机密信息 |
config.yaml | 所有 Hermes 配置 |
SOUL.md | Agent 人格/身份 |
sessions/ | 对话历史 |
memories/ | 持久记忆存储 |
skills/ | 已安装的技能 |
cron/ | 定时任务定义 |
hooks/ | 事件钩子 |
logs/ | 运行时日志 |
skins/ | 自定义 CLI 皮肤 |
:::warning 切勿同时针对同一数据目录运行两个 Hermes 网关容器——会话文件和记忆存储不设计用于并发写入访问。 :::
多配置文件支持
Hermes 支持多个配置文件——单独的 ~/.hermes/ 目录,让你从单个安装中运行独立的 agent(不同的 SOUL、技能、记忆、会话、凭据)。在 Docker 下运行时,不建议使用 Hermes 内置的多配置文件功能。
相反,推荐的模式是每个配置文件一个容器,每个容器将其自己的主机目录绑定挂载为 /opt/data:
# 工作配置文件
docker run -d \
--name hermes-work \
--restart unless-stopped \
-v ~/.hermes-work:/opt/data \
-p 8642:8642 \
nousresearch/hermes-agent gateway run
# 个人配置文件
docker run -d \
--name hermes-personal \
--restart unless-stopped \
-v ~/.hermes-personal:/opt/data \
-p 8643:8642 \
nousresearch/hermes-agent gateway run为什么在 Docker 中为每个配置文件使用独立容器而非内置配置文件:
- 隔离性——每个容器拥有自己的文件系统、进程表和资源限制。一个配置文件中的崩溃、依赖变更或失控会话不会影响另一个。
- 独立生命周期——分别升级、重启、暂停或回滚每个 agent(
docker restart hermes-work不会影响hermes-personal)。 - 清晰的端口和网络分离——每个网关绑定自己的主机端口;聊天平台或 API 服务器之间没有串扰风险。
- 更简单的思维模型——容器就是配置文件。备份、迁移和权限都遵循绑定挂载的目录,无需记住额外的
--profile标志。 - 避免并发写入风险——上面关于切勿针对同一数据目录运行两个网关的警告同样适用于单个容器内的配置文件。
在 Docker Compose 中,只需为每个配置文件声明一个服务,使用不同的 container_name、volumes 和 ports:
services:
hermes-work:
image: nousresearch/hermes-agent:latest
container_name: hermes-work
restart: unless-stopped
command: gateway run
ports:
- "8642:8642"
volumes:
- ~/.hermes-work:/opt/data
hermes-personal:
image: nousresearch/hermes-agent:latest
container_name: hermes-personal
restart: unless-stopped
command: gateway run
ports:
- "8643:8642"
volumes:
- ~/.hermes-personal:/opt/data环境变量转发
API 密钥从容器内的 /opt/data/.env 读取。你也可以直接传递环境变量:
docker run -it --rm \
-v ~/.hermes:/opt/data \
-e ANTHROPIC_API_KEY="sk-ant-..." \
-e OPENAI_API_KEY="sk-..." \
nousresearch/hermes-agent直接 -e 标志会覆盖 .env 中的值。这对于 CI/CD 或密钥管理器集成(你不想将密钥保存在磁盘上)很有用。
:::note 寻找 Docker 作为终端后端?
本页介绍在 Docker 内部运行 Hermes 本身。如果你希望 Hermes 在 Docker 沙箱容器内执行 agent 的 terminal / execute_code 调用(每个 Hermes 进程一个持久容器),那是另一个配置块——terminal.backend: docker 加上 terminal.docker_image、terminal.docker_volumes、terminal.docker_forward_env、terminal.docker_run_as_host_user 和 terminal.docker_extra_args。完整设置请参阅配置 → Docker 后端。
:::
Docker Compose 示例
对于网关和仪表盘同时存在的持久部署,使用 docker-compose.yaml 很方便:
services:
hermes:
image: nousresearch/hermes-agent:latest
container_name: hermes
restart: unless-stopped
command: gateway run
ports:
- "8642:8642" # 网关 API
- "9119:9119" # 仪表盘(仅当 HERMES_DASHBOARD=1 时可达)
volumes:
- ~/.hermes:/opt/data
environment:
- HERMES_DASHBOARD=1
# 取消注释以转发特定环境变量而非使用 .env 文件:
# - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
# - OPENAI_API_KEY=${OPENAI_API_KEY}
# - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
deploy:
resources:
limits:
memory: 4G
cpus: "2.0"使用 docker compose up -d 启动,使用 docker compose logs -f 查看日志。仪表盘输出以 [dashboard] 为前缀,便于从网关日志中过滤。
资源限制
Hermes 容器需要适度的资源。推荐的最低配置:
| 资源 | 最低要求 | 推荐 |
|---|---|---|
| 内存 | 1 GB | 2–4 GB |
| CPU | 1 核 | 2 核 |
| 磁盘(数据卷) | 500 MB | 2+ GB(随会话/技能增长) |
浏览器自动化(Playwright/Chromium)是最消耗内存的功能。如果不需要浏览器工具,1 GB 就足够了。如果使用浏览器工具,请分配至少 2 GB。
在 Docker 中设置限制:
docker run -d \
--name hermes \
--restart unless-stopped \
--memory=4g --cpus=2 \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent gateway runDockerfile 的内容
官方镜像基于 debian:13.4,包含:
- Python 3 及所有 Hermes 依赖(
uv pip install -e ".[all]") - Node.js + npm(用于浏览器自动化和 WhatsApp 桥接)
- 带 Chromium 的 Playwright(
npx playwright install --with-deps chromium --only-shell) - ripgrep、ffmpeg、git 和 tini 作为系统工具
docker-cli——以便容器内运行的 agent 可以驱动主机的 Docker 守护进程(绑定挂载/var/run/docker.sock以选择加入),用于docker build、docker run、容器检查等。openssh-client——从容器内启用 SSH 终端后端。SSH 后端会调用系统ssh二进制文件;没有此客户端,它会在容器化安装中静默失败。- WhatsApp 桥接(
scripts/whatsapp-bridge/)
入口点脚本(docker/entrypoint.sh)在首次运行时引导数据卷:
- 创建目录结构(
sessions/、memories/、skills/等) - 如果不存在
.env,复制.env.example→.env - 如果缺少,复制默认的
config.yaml - 如果缺少,复制默认的
SOUL.md - 使用基于清单的方法同步预装技能(保留用户编辑)
- 可选:当
HERMES_DASHBOARD=1时以后台副进程方式启动hermes dashboard(请参阅运行仪表盘) - 然后使用你传递的任何参数运行
hermes
:::warning
除非你在命令链中保留 /opt/hermes/docker/entrypoint.sh,否则不要覆盖镜像入口点。入口点在创建网关状态文件之前将 root 权限降级为 hermes 用户。以 root 身份在官方镜像内启动 hermes gateway run 默认会被拒绝,因为这会在 /opt/data 中留下 root 拥有的文件,并破坏后续的仪表盘或网关启动。仅在你明确接受该风险时设置 HERMES_ALLOW_ROOT_GATEWAY=1。
:::
升级
拉取最新镜像并重新创建容器。你的数据目录不受影响。
docker pull nousresearch/hermes-agent:latest
docker rm -f hermes
docker run -d \
--name hermes \
--restart unless-stopped \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent gateway run或使用 Docker Compose:
docker compose pull
docker compose up -d技能和凭据文件
当使用 Docker 作为执行环境时(不是上述方式,而是 agent 在 Docker 沙箱内运行命令——请参阅配置 → Docker 后端),Hermes 会为所有工具调用复用一个长期运行的容器,并自动将技能目录(~/.hermes/skills/)和技能声明的任何凭据文件以只读卷方式绑定挂载到该容器中。技能脚本、模板和引用在沙箱内可用,无需手动配置;并且由于容器在 Hermes 进程的生命周期内持续存在,你安装的任何依赖或写入的文件都会为下一次工具调用保留。
SSH 和 Modal 后端也会进行相同的同步——技能和凭据文件会在每次命令前通过 rsync 或 Modal 挂载 API 上传。
连接本地推理服务器(vLLM、Ollama 等)
当在 Docker 中运行 Hermes,且你的推理服务器(vLLM、Ollama、text-generation-inference 等)也在主机上或在另一个容器中运行时,网络连接需要额外注意。
Docker Compose(推荐)
将两个服务放在同一个 Docker 网络上。这是最可靠的方法:
services:
vllm:
image: vllm/vllm-openai:latest
container_name: vllm
command: >
--model Qwen/Qwen2.5-7B-Instruct
--served-model-name my-model
--host 0.0.0.0
--port 8000
ports:
- "8000:8000"
networks:
- hermes-net
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
hermes:
image: nousresearch/hermes-agent:latest
container_name: hermes
restart: unless-stopped
command: gateway run
ports:
- "8642:8642"
volumes:
- ~/.hermes:/opt/data
networks:
- hermes-net
networks:
hermes-net:
driver: bridge然后在你的 ~/.hermes/config.yaml 中,使用容器名称作为主机名:
model:
provider: custom
model: my-model
base_url: http://vllm:8000/v1
api_key: "none":::tip 要点
- 使用容器名称(
vllm)作为主机名——不要使用localhost或127.0.0.1,它们指向 Hermes 容器本身。 model值必须与你传递给 vLLM 的--served-model-name匹配。- 将
api_key设置为任何非空字符串(vLLM 需要该头文件但默认不验证)。 base_url中不要包含尾部斜杠。 :::
独立 Docker 运行(无 Compose)
如果你的推理服务器直接在主机上运行(不在 Docker 中),在 macOS/Windows 上使用 host.docker.internal,在 Linux 上使用 --network host:
macOS / Windows:
docker run -d \
--name hermes \
-v ~/.hermes:/opt/data \
-p 8642:8642 \
nousresearch/hermes-agent gateway run# config.yaml
model:
provider: custom
model: my-model
base_url: http://host.docker.internal:8000/v1
api_key: "none"Linux(主机网络):
docker run -d \
--name hermes \
--network host \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent gateway run# config.yaml
model:
provider: custom
model: my-model
base_url: http://127.0.0.1:8000/v1
api_key: "none":::warning 使用 --network host 时,-p 标志被忽略——所有容器端口直接在主机上暴露。
:::
验证连接
从 Hermes 容器内部,确认推理服务器可达:
docker exec hermes curl -s http://vllm:8000/v1/models你应该看到列出已服务模型的 JSON 响应。如果失败,请检查:
- 两个容器在同一个 Docker 网络上(
docker network inspect hermes-net) - 推理服务器正在监听
0.0.0.0,而非127.0.0.1 - 端口号匹配
Ollama
Ollama 的工作方式相同。如果 Ollama 在主机上运行,使用 host.docker.internal:11434(macOS/Windows)或 127.0.0.1:11434(Linux 使用 --network host)。如果 Ollama 在同一个 Docker 网络上的自己的容器中运行:
model:
provider: custom
model: llama3
base_url: http://ollama:11434/v1
api_key: "none"故障排除
容器立即退出
检查日志:docker logs hermes。常见原因:
- 缺少或无效的
.env文件——先以交互方式运行以完成设置 - 端口冲突(如果使用暴露的端口运行)
“Permission denied”错误
容器的入口点通过 gosu 将权限降级为非 root 的 hermes 用户(UID 10000)。如果你的主机 ~/.hermes/ 由不同的 UID 所有,请设置 HERMES_UID/HERMES_GID 以匹配你的主机用户,或确保数据目录可写:
chmod -R 755 ~/.hermes浏览器工具无法工作
Playwright 需要共享内存。在 Docker 运行命令中添加 --shm-size=1g:
docker run -d \
--name hermes \
--shm-size=1g \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent gateway run网络问题后网关无法重新连接
--restart unless-stopped 标志处理大多数瞬时故障。如果网关卡住,重启容器:
docker restart hermes检查容器健康状态
docker logs --tail 50 hermes # 最近日志
docker run -it --rm nousresearch/hermes-agent:latest version # 验证版本
docker stats hermes # 资源使用情况