不少团队不仅把 Automatic1111(AUTOMATIC1111 stable-diffusion-webui)当图形界面用,还直接把它当 HTTP API 层。在这种架构上扩缩容时,冷启动少几秒往往就是少付几轮排队与超时——如果你正在压 A1111 的安装与启动时间,下面的两条 Docker 级思路很实用。
参考仓库
说明(2026 年核对):主分支上可能已看不到与当年完全一致的 tree/main/serverless-automatic 路径,同类逻辑常出现在 archived/stable-diffusion-webui 或新版 official-templates 中。本文聚焦 方法论,具体 Dockerfile 行请以你实际 fork 的模板为准。
两条优化分别解决什么?
- 把 Hugging Face 侧需要的文件提前拉进镜像缓存 避免每次 Serverless 冷启动 再从公网下载同一批文件。
- 在构建期预计算模型哈希并写入缓存文件 避免容器每次启动时再跑一遍耗 CPU 的扫描与校验。
在当时的示例里,这两项通常集中在 执行 cache.py 的 Dockerfile 步骤 中完成(构建镜像时跑一次,而不是请求来了再跑)。
cache.py 在做什么?
cache.py 本身并不「魔法」:它会从 WebUI 本体里 import 若干函数(来自 webui、modules 等),在 非交互、构建阶段 的环境下把初始化流程跑一段。
效果上可以拆成两件大事:
1)预热 Hugging Face 缓存
脚本会触发下载并把文件放进默认缓存目录,例如:
/root/.cache/huggingface如果你在打 无服务器镜像 时跳过这一步,那么 每一个冷启动的 Pod 都可能重新走一遍下载——网络抖动时尤其致命。
2)预计算哈希并写入 cache.json
计算结果会落到 WebUI 约定路径,例如:
/workspace/stable-diffusion-webui/cache.json默认行为下,A1111 也可能在启动时自动做这件事;因此冷启动会明显吃 CPU。你也可以用命令行参数 --no-hashing 关掉启动时哈希,但更适合生产的方式往往是:构建期就算好并落盘,运行时直接读缓存。
Dockerfile 里怎么接?
思路是:在 已经安装好 WebUI 与依赖 之后,增加一步显式执行预热脚本(路径按你的仓库调整):
RUN python /workspace/serverless-automatic/cache.py实际模板里可能是 WORKDIR + RUN python cache.py 等形式,和当时 serverless-automatic 的目录布局一致即可。
优化前 vs 优化后(定性结论)
原文给出的对比是:做完 HF 缓存 + 预计算哈希之后,冷启动路径会少掉「每次现下文件」和「每次现算哈希」两大块 同步 CPU/IO 尖峰。具体秒数依赖模型体积、磁盘与 CPU 型号,但方向是稳定的:把能在镜像里做完的事,不要交给 Serverless 的第一次请求。
额外观察:启动时间很吃 CPU,尤其单核
启动耗时与 CPU 关系很大,甚至与 单核性能 近似线性相关。也就是说,换更快的实例规格(尤其单核频率更高的 CPU)对「从进程起来到 API 可服务」同样有效,和 Docker 缓存是 互补 关系,不是二选一。
此外,导入 PyTorch、Gradio 等重型依赖本身仍要时间;后续文章还会专门讲如何压缩 import 时间——若你今天的瓶颈已经不在下载与哈希,而卡在 解释器 import,就需要另开一轮优化(例如延迟导入、精简依赖、换更瘦的启动路径等)。
小结
手段 | 作用 |
构建期跑 | 把 HF 文件写入镜像层或构建期可复用层,避免冷启动下载 |
预写 | 避免启动阶段全量模型哈希,降低 CPU 尖峰与尾延迟 |
更快 CPU / 更高单核 | 与镜像优化正交,直接缩短 import 与 Python 启动段 |
把「构建期一次性」和「运行时每次」分清,是无服务器服务能否稳定承接流量的分水岭之一。