Hermes Agent 容器镜像瘦身与启动加速指南:体积减半、冷启动提速
2026/8/28 11:14:53 网站建设 项目流程

Hermes Agent 容器镜像瘦身与启动加速指南:体积减半、冷启动提速

【免费下载链接】hermes-agentThe agent that grows with you项目地址: https://gitcode.com/GitHub_Trending/he/hermes-agent

生产 VPS 上跑 Hermes Agent 的同事上个月遇到了一个典型问题:镜像从 2 GB 悄悄涨到 5 GB,一次例行更新,拉取从几分钟变成四十分钟;冷启动更糟,容器起来了,第一次进聊天页还要现场跑npm install,agent 干等着,任务延迟全记在账单上。这类问题很少是某一个"大文件"造成的,而是镜像里每层都在悄悄叠加开发期产物。本文的思路是四步:先分层诊断,再裁剪依赖,然后调整层的顺序让缓存真正生效,最后把启动路径预热掉。做完后镜像体积通常能压到原来的 1/3 ~ 1/2,冷启动从分钟级回到十秒以内。

Hermes Agent 是 Nous Research 开源的自学习智能体:它会从任务中沉淀技能、跨会话检索自己的历史对话,通过 Docker 部署到 VPS 或集群,再从 Telegram、Discord 等消息平台接入。它的镜像同时装着 Python venv、Node 依赖、前端产物、Chromium,这类多运行时栈的镜像最容易膨胀,也最容易优化出成果。

诊断镜像分层,看清体积从哪来

为什么先诊断?因为镜像是逐层堆出来的,直接删东西很容易误伤。Hermes 的镜像里甚至有一个专门为 SQLite 单独立的阶段:Debian 13 自带的 SQLite 3.46.1 存在上游 WAL 重置 bug,官方源没有回移补丁,所以单独编译一个带 FTS5 的共享库拷进运行时,构建用的工具链和源码全部留在上一个阶段。不先看清每层是什么,你根本不知道哪些能砍、哪些砍了会坏。

怎么做?拉下镜像后按层列大小:

docker history --no-trunc --format "table {{.Size}}\t{{.CreatedBy}}" <image> | head -20

能拿到什么?最大的一两块通常是.venvnode_modules,第三块是 Playwright 的 Chromium。有了这张清单,"减到多少算合理"才有判断依据:依赖装不进更小的是正常的,但开发工具链、测试目录、文档站点出现在运行镜像里,就是该砍的对象。

上图是 Hermes Agent 桌面端的会话界面,左侧按来源(Telegram、Discord、WebUI)分组的历史会话都跑在同一个 agent 后端上——这类多运行时栈的镜像,正是分层诊断最有价值的对象。

裁剪依赖集合,把开发期产物排除在运行时之外

为什么会有浪费?多运行时项目的依赖树往往按"场景"分组,全量安装会把训练、基准测试、开发调试的包一起拖进来。

怎么做?Hermes 把依赖按 extra 分组,构建镜像时只取手工挑选的生产集合,外加网关消息适配和几个 provider SDK,刻意不用--all-extras

uv sync --frozen --no-install-project \ --extra all --extra messaging --extra otlp --extra matrix

被排除的[rl]extra 里是 torch、wandb 这类从 git 拉的重型包,单是它们就能占几百 MB 到 1 GB 量级。代码侧同理:项目根的.dockerignoretests/docs/、文档站点、桌面端源码、打包元数据全部挡在构建上下文外,镜像里只剩运行必需的东西。

能拿到什么?通常省 20% ~ 40% 的镜像体积,且不影响任何生产路径——被排除的 extra 只有对应场景才需要,届时在卷上懒装即可。

重排构建层,让依赖缓存真正命中

为什么缓存经常失效?常见写法是把源码整个COPY . .之后再装依赖,这样改一行代码就使依赖层失效,CI 每次冷构建都重新下载、重新编译。

怎么做?把"清单"和"源码"拆到不同层,且清单先于源码:

COPY pyproject.toml uv.lock package.json package-lock.json ./ RUN uv sync --frozen --no-install-project ... COPY --link --chmod=a+rX,go-w . .

这样只有清单或 lockfile 变化才重跑依赖安装;纯源码提交直接命中缓存。Hermes 的 Dockerfile 里 Python 部分就是这种拆法,注释里记录了代价:拆分前,依赖层排在COPY . .之后,每次纯源码提交的冷构建要多花 4~5 分钟重复装依赖;npm 一侧也是先只拷 manifest 再npm install,最后才编前端。

能拿到什么?重复构建通常快一半以上,而且构建时间稳定可预期——这对 CI 排队和资源占用是实打实的收益。

预热启动路径,别让容器启动时干构建期的活

为什么冷启动慢?因为镜像构建期没做完的事,会在容器启动后补做:现场npm install、懒装 SDK、首次编译。这些步骤既慢又容易失败,并发进来时还会互相竞争。

怎么做?两条原则。第一,能构建期做完的就构建期做完:Hermes 把前端 TUI 在构建期编好,运行时环境变量指向预编译 bundle,直接跳过启动时npm install分支。第二,运行时必须可写的部分放进挂载卷,别放镜像层:镜像层是只读的,容器一重建,卷之外的懒装产物就丢。Hermes 把代码目录密封为只读、数据目录挂卷,懒装目标指向卷上可写目录,并追加在sys.path末尾——只增模块、不覆盖核心包:

HERMES_LAZY_INSTALL_TARGET=/opt/data/lazy-packages

能拿到什么?冷启动路径上的重活基本清零,首次进 TUI、聊天页、启用某个搜索后端,通常都是秒级就绪;容器重建、镜像升级后,懒装组件也不会再丢。

这张是项目里用于界面填充的蓝色插画,和 agent"陪你成长"的定位呼应——部署层做的事也是同一件事:让运行时只保留成长需要的部分。

用一套自检清单验收优化效果

改完别只看体积数字,按下面几项过一遍:

  1. docker history --no-trunc <image>:最大三层应是 venv、Chromium、Node 依赖,不应再出现开发工具链、测试与文档目录。
  2. 总体积对比优化前:期望在 1/3 ~ 1/2 区间(约 1~3 GB,含 Playwright 时偏上限),接近原生python:3.x基础镜像体积说明裁剪没生效。
  3. 启动计时:容器创建到 TUI/dashboard 可用,期望十秒级;首次进聊天页若触发npm install,说明前端产物没在构建期编好。
  4. 权限与数据面:/opt/hermes对普通用户只读、/opt/data可写,容器重建后懒装组件仍在。
  5. 构建期自检:SQLite 版本与 FTS5 的自检应在构建期通过,运行时不再触发任何编译。

这几项全部过掉,说明"诊断 → 裁剪 → 调层序 → 预热启动"的闭环是有效的。这套思路不依赖 Hermes 的具体配置,任何多运行时栈的 agent 镜像都可以照着落地——项目根目录的 Dockerfile 和 .dockerignore 就是完整的参考实现,可以直接对照检查自己镜像里的每一层。

【免费下载链接】hermes-agentThe agent that grows with you项目地址: https://gitcode.com/GitHub_Trending/he/hermes-agent

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询