想在本地拥有自己的 AI 绘画引擎?ComfyUI 部署 Stable Diffusion 是目前最灵活的开源方案:用节点式工作流把文生图、图生图、ControlNet 串成可复用管线,数据不出本机、出图成本趋近于零。本文从硬件准备、Docker 一键启动,到 API 批量化与 FastAPI 封装,带你把 Stable Diffusion 真正跑在自有显卡上。
一、ComfyUI 是什么,为什么选它
ComfyUI 是一个基于节点(Node)的 Stable Diffusion 可视化工作流引擎。相比传统的 A1111 WebUI 单页参数面板,ComfyUI 把”加载模型 → 编码潜空间 → 采样 → VAE 解码 → 保存”拆成一张可拖拽、可保存的图。你调好的流程能导出成 JSON,下次一键复现,天然适合工程化与批量出图。
A1111 的优势是开箱即用、插件生态丰富;但当你的需求从”玩一玩”变成”每天稳定产出几百张、且流程要可复现”时,节点图的价值就凸显了。每个节点只做一件事,出错时能精确定位到某个模块,而不是面对一整页互相影响的滑块。
| 维度 | ComfyUI | A1111 WebUI |
|---|---|---|
| 工作流 | 节点图,可导出 JSON 复用 | 单页参数,难复用 |
| 显存占用 | 较低(图执行优化) | 较高 |
| 进阶能力 | ControlNet / 自定义节点强 | 插件多但偏重 |
| 工程化 | API 友好,易接入服务 | 相对较弱 |
二、硬件与环境准备
本地出图本质是显卡算力消耗。经验阈值:SD1.5 约 4GB 显存可跑;SDXL 建议 8GB 以上;若想上 Flux 这类大模型,16GB 显存更从容。AMD 显卡与纯 CPU 也能跑,但速度会慢一个数量级,本文以 NVIDIA + CUDA 为准。
还有一个常被忽略的点:CUDA 版本要和 PyTorch 编译版本匹配。用 pip 安装时务必带上对应的 index-url(如 cu121),否则会出现”能 import 但一跑就报 CUDA error”的诡异问题。容器方案之所以省心,正是因为它把这套依赖打包好了。
- 显卡驱动与 CUDA 已装好(
nvidia-smi能看到显卡); - Python 3.10 / 3.11,并准备
git; - 磁盘预留 10GB+ 给模型权重(一个 SDXL checkpoint 约 6–7GB)。
三、两种启动方式
方式 A:Docker 一键启动(推荐)
用官方 GHCR 镜像,配合 docker-compose 挂载模型与输出目录,GPU 通过 device reservation 透传。这也是我们最推荐的起步方式,环境一致性最好:
services:
comfyui:
image: ghcr.io/comfyanonymous/comfyui:latest
container_name: comfyui
ports:
- "8188:8188"
volumes:
- ./models:/home/runner/models
- ./output:/home/runner/output
- ./input:/home/runner/input
command: --listen 0.0.0.0 --port 8188 --use-xformers --lowvram
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
restart: unless-stopped
启动后用浏览器打开 http://<服务器IP>:8188 即可进入节点画布。容器化部署的更多细节可参考我们的 Docker 容器化实战。
方式 B:源码安装
如果你要改源码、加自定义节点,或服务器没有 Docker,就走源码路线:
# 1) 拉取官方源码
git clone https://github.com/comfyanonymous/ComfyUI.git
cd ComfyUI
# 2) 创建虚拟环境并安装依赖(CUDA 12.1 为例)
python -m venv venv && source venv/bin/activate
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
pip install -r requirements.txt
# 3) 启动:开启 xformers 与低显存模式
python main.py --listen 0.0.0.0 --port 8188 --use-xformers --lowvram
四、第一次出图:模型与工作流
ComfyUI 本体不含模型权重,需要自行把 checkpoint 放到 models/checkpoints 目录(容器场景即挂载的 ./models/checkpoints)。常见来源有 HuggingFace 与 Civitai,下载后直接放进去,刷新页面即可在 Load Checkpoint 节点看到。
一个最基础的文生图工作流由这些节点串成:Load Checkpoint → CLIP Text Encode(正/负提示词) → Empty Latent Image → KSampler → VAE Decode → Save Image。在 KSampler 里设置步数(20–30)、CFG(7 左右)、采样器(如 dpmpp_2m),填好提示词,点 Queue Prompt 就能出图。
正向提示词描述你”想要什么”,负向提示词描述”不要什么”(如低质量、变形、水印)。初学时可以先套用社区成熟的提示词模板,等理解了各参数对画面的影响,再逐步微调。
五、用 API 批量化出图
ComfyUI 的真正优势在工程化:在 WebUI 里把工作流调好后,点 “Save (API Format)” 导出 JSON,就能用 HTTP 接口批量提交,而不必手动点界面。导出的 JSON 里每个节点都有一个数字 id,修改对应节点的 inputs 字段即可换提示词或种子。
import json, requests
# 1) 载入 API 格式工作流(里面已固化节点连接)
with open("workflow_api.json") as f:
prompt = json.load(f)
# 2) 提交到 ComfyUI 任务队列
r = requests.post("http://127.0.0.1:8188/prompt", json={"prompt": prompt})
task_id = r.json()["prompt_id"]
# 3) 轮询历史拿到结果图片
while True:
hist = requests.get(f"http://127.0.0.1:8188/history/{task_id}").json()
if task_id in hist:
outputs = hist[task_id]["outputs"]
break
把不同的提示词塞进同一个 workflow JSON 的对应节点,就能实现”一张模板、千条文案”的批量生成,非常适合电商素材、头像、配图等场景。ComfyUI 内部是队列调度,多个任务会按顺序执行,不必自己写并发控制。
六、显存优化与模型管理
显存是本地出图的第一道坎。除了启动时加 --lowvram / --medvram,还可以用 GGUF 量化版的 checkpoint 大幅减负,并开启 --use-xformers 提速。本地大模型的显存策略思路与 DeepSeek 本地部署实战 一脉相承:都是”算力不够,量化来凑”。
模型目录结构要分门别类放好,否则节点会”找不到”对应的权重。一个清晰的目录约定如下:
| 目录 | 放什么 |
|---|---|
| models/checkpoints | 主模型权重(.safetensors / .ckpt / .gguf) |
| models/vae | VAE 解码器(解决出图发灰/偏色) |
| models/loras | 风格微调模型 |
| models/controlnet | 姿态/线稿等控制模型 |
七、封装成出图服务
要让前端页面或定时脚本调用出图,最自然的方式是用 FastAPI 包一层 HTTP 服务。这与我们之前写的 FastAPI 流式大模型对话 API 思路一致:把后端能力收敛成干净的接口,对外只暴露业务语义,不暴露底层细节。
from fastapi import FastAPI
import requests, json
app = FastAPI()
def build_prompt(text: str, seed: int = 0) -> dict:
wf = json.load(open("workflow_api.json"))
# 把 text/seed 写回对应节点字段(示意)
wf["6"]["inputs"]["text"] = text
wf["3"]["inputs"]["seed"] = seed
return wf
@app.post("/generate")
def generate(req: dict):
prompt = build_prompt(req["text"], req.get("seed", 0))
r = requests.post("http://127.0.0.1:8188/prompt", json={"prompt": prompt})
return {"task_id": r.json()["prompt_id"]}
生产环境用 uvicorn main:app --workers 2 起多进程,并在前面挂一层队列或限流,避免瞬间大量请求把显存打爆。配合 VS Code 远程开发,以及用 GitHub Actions 把工作流 JSON 纳入版本管理,做到可复现、可回滚。
八、安全暴露与反代
ComfyUI 默认没有鉴权,切勿直接把 8188 端口暴露在公网。正确做法是放在内网,再用 Nginx 反向代理 套一层 HTTPS 与访问口令(如 basic auth 或带 token 的网关),既方便远程访问,又不把裸服务暴露出去。
一个最小可用的 Nginx 反代片段形如:把 / 转发到 127.0.0.1:8188,并加上 auth_basic 保护。这样你的出图服务既能从笔记本访问,又不会被公网扫描器随意调用。
九、常见问题排障
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 显存不足 / CUDA OOM | 模型或分辨率过大 | 加 –lowvram、降分辨率、换 GGUF 量化模型 |
| 出图全黑或发灰 | VAE 不匹配或未加载 | 在节点显式指定对应 VAE |
| 模型列表为空 | 目录放错 | 确认放在 models/checkpoints |
| 页面打不开 | 端口/防火墙 | 检查 8188 与反代配置 |
十、进阶路线
跑通基础出图后,值得继续探索三条路:一是 ControlNet,用姿态、线稿、深度图精确控制构图;二是 LoRA,用少量图片微调出专属风格;三是把出图接入更复杂的流水线,例如先 LLM 写提示词、再 ComfyUI 出图、最后自动上传素材库。把这三块吃透,本地 AI 绘画就能从”玩具”变成”生产力”。
到这里,你已经拥有了一套可复用、可批量化、可对外服务的本地 AI 绘画管线。下一步可以接入 ControlNet 做姿态控制、用 LoRA 固化风格,甚至把出图能力嵌进你自己的产品里。



