Stable Diffusion 3.5 FP8 文生图实战:我做了一个“可复用 AI 镜像”(Docker + FastAPI),把部署从“装环境”变成“一条命令起服务”
本文介绍了如何将Stable Diffusion 3.5 FP8文生图模型封装为可复用的Docker镜像,解决环境配置、资源管理和服务标准化问题。作者采用两种推理路线:Diffusers Pipeline快速实现API化,以及TensorRT+FP8优化提升性能。通过Dockerfile固定CUDA环境,FastAPI提供标准化接口,实现从"装环境"到"一条命令起服务
文章目录
- Stable Diffusion 3.5 FP8 文生图实战:我做了一个“可复用 AI 镜像”(Docker + FastAPI),把部署从“装环境”变成“一条命令起服务”
-
- 0. 我这次想解决的到底是什么问题
- 1. 为什么我盯上 SD3.5 + FP8(而不是只做 FP16)
- 2. 我做的“AI 镜像”长什么样:一张图说清组件关系
- 3. 我选择的两条推理路线
- 4. 我镜像里的目录结构(我习惯这样摆)
- 5. Dockerfile:我怎么把“环境地狱”封进镜像
- 6. FastAPI:我怎么把“文生图脚本”变成“可用服务”
- 7. 推理封装:Diffusers 版本(先跑通)
- 8. 我怎么跑起来:构建、启动、请求一气呵成
- 9. FP8 / TensorRT 我怎么接(我把它当“第二阶段强化”)
- 10. 我最后的总结
- 参考链接(方便我贴到 CSDN 参考区)
- (可选)我给自己留的“技术自测题”
Stable Diffusion 3.5 FP8 文生图实战:我做了一个“可复用 AI 镜像”(Docker + FastAPI),把部署从“装环境”变成“一条命令起服务”
这篇是我参加「AI 镜像开发实战征文活动」的实战总结:围绕 Stable Diffusion 3.5 FP8 做一个可复用、可移植、可上线的镜像(容器镜像 / 环境镜像都算),目标是把“文生图服务”变成标准化组件。
0. 我这次想解决的到底是什么问题
我在做文生图项目时,反复踩到三个坑:
- 环境不一致:显卡驱动、CUDA、PyTorch、Diffusers、各种依赖一变就炸
- 资源不可控:显存不够、加载太慢、启动时间不可预期
- 上线不标准:脚本能跑 ≠ 服务可用(API、日志、缓存、复现都缺)
所以我给自己的要求是三句话:
- 能在“干净机器”上复现(可复用)
- 能跑 FP8 / TensorRT 路线(可优化)
- 能提供 API(可集成 / 可上线)
1. 为什么我盯上 SD3.5 + FP8(而不是只做 FP16)
SD3 系列在 Diffusers 侧的一个关键特征是:pipeline 会用到三个文本编码器,并且官方文档明确提到:为了在大多数“常规硬件”上跑起来,经常需要做 offload(比如 CPU/GPU 卸载)。(huggingface.co)
而 SD3.5 的“FP8 + TensorRT”路线,给了我一个非常工程化的收益点:更快 + 更省显存。Stability AI 与 NVIDIA 的公开信息提到,SD3.5 家族在 TensorRT + FP8 优化后可以带来显著性能提升与显存下降。(Stability AI)
另外,Hugging Face 上也提供了 TensorRT 优化版本的 SD3.5 Large,并说明其中包含 FP8 精度的 MMDiT(核心 transformer)导出与量化产物,同时给了示例脚本与性能表。(huggingface.co)
2. 我做的“AI 镜像”长什么样:一张图说清组件关系
我把它拆成 6 块:请求入口、API、队列(可选)、GPU Worker、模型缓存、产物存储。

这个结构的重点不是“多复杂”,而是每一块都能单独替换:
- 我可以把 FastAPI 换成 Gradio / Streamlit
- 我可以把 Worker 换成 TensorRT 路线 / Diffusers 路线
- 我可以把存储换成本地磁盘 / 对象存储
3. 我选择的两条推理路线
3.1 路线 A:Diffusers Pipeline(先跑通、再优化)
我用 StableDiffusion3Pipeline 这条线的原因很朴素:工程集成成本低,而且 SD3 pipeline 的关键特性(3 个文本编码器、offload 建议)在官方文档里写得很清楚。(huggingface.co)
如果我只是要“跑起来 + API 化”,路线 A 最快落地。
3.2 路线 B:TensorRT + FP8(把“能用”推进到“能打”)
如果我追求更稳定的线上吞吐和显存占用,我会直接对齐官方提供的 TensorRT 优化仓库:
- HF 的
stable-diffusion-3.5-large-tensorrt说明了 ONNX 导出(BF16)+ FP8 的 MMDiT,并给出示例推理命令与引擎构建参数。(huggingface.co) - 这条路线的核心价值就是:把“PyTorch 生态的不确定性”收敛到“推理引擎的确定性”
我把官方公开收益画成了一张概念图(不是我实测数据,而是对公开信息的可视化):

4. 我镜像里的目录结构(我习惯这样摆)
sd35-fp8-mirror/
├── Dockerfile
├── requirements.txt
├── app.py # FastAPI
├── sd_infer.py # 推理封装(Diffusers / TRT 可二选一)
└── README.md
5. Dockerfile:我怎么把“环境地狱”封进镜像
我用 CUDA Runtime 基础镜像是为了减少和宿主机 CUDA 的扯皮;同时把 HF 缓存挂载出来,避免每次重启都重新拉权重。
FROM nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
HF_HOME=/cache/huggingface \
TRANSFORMERS_CACHE=/cache/huggingface \
HF_HUB_ENABLE_HF_TRANSFER=1
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 python3-pip git curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt /app/requirements.txt
RUN python3 -m pip install --upgrade pip && pip install -r requirements.txt
COPY app.py sd_infer.py /app/
EXPOSE 8000
CMD ["uvicorn", "app:api", "--host", "0.0.0.0", "--port", "8000"]
requirements.txt(我会把版本锁住,减少漂移):
fastapi==0.115.0
uvicorn[standard]==0.30.6
pydantic==2.8.2
pillow==10.4.0
torch
transformers
diffusers
accelerate
safetensors
huggingface_hub
6. FastAPI:我怎么把“文生图脚本”变成“可用服务”
我把推理封装成一个 generate(),API 只负责:入参校验、seed 控制、返回图片字节流。
# app.py
from fastapi import FastAPI
from pydantic import BaseModel, Field
from fastapi.responses import Response
from sd_infer import get_engine
api = FastAPI(title="SD3.5 FP8 Mirror API")
class T2I(BaseModel):
prompt: str = Field(..., min_length=1)
negative_prompt: str | None = None
width: int = 1024
height: int = 1024
steps: int = 30
guidance_scale: float = 3.5
seed: int | None = None
engine = get_engine() # 懒加载/单例
@api.post("/v1/txt2img")
def txt2img(req: T2I):
img_bytes = engine.generate(
prompt=req.prompt,
negative_prompt=req.negative_prompt,
width=req.width,
height=req.height,
steps=req.steps,
guidance_scale=req.guidance_scale,
seed=req.seed,
)
return Response(content=img_bytes, media_type="image/png")
我把“工程可用性”放在第一位:
- 参数都可控(steps / seed / guidance 等)
- 输出格式固定(PNG)
- 结构清晰,后续接队列、加鉴权、加日志都不会拆大梁
7. 推理封装:Diffusers 版本(先跑通)
下面这个 sd_infer.py 我写得很“朴素”:
- 默认 FP16/BF16
- 显存紧张时可以做 offload(SD3 文档明确提到 offloading 的必要性倾向)(huggingface.co)
# sd_infer.py(Diffusers 路线示例)
import io
import torch
from PIL import Image
from diffusers import StableDiffusion3Pipeline
_MODEL_ID = "stabilityai/stable-diffusion-3.5-large" # 需要在 HF 同意协议后可拉取 :contentReference[oaicite:6]{index=6}
class DiffusersEngine:
def __init__(self):
dtype = torch.bfloat16 if torch.cuda.is_available() else torch.float32
self.pipe = StableDiffusion3Pipeline.from_pretrained(_MODEL_ID, torch_dtype=dtype)
if torch.cuda.is_available():
self.pipe.to("cuda")
# 机器显存不宽裕时,可以考虑:
# self.pipe.enable_model_cpu_offload()
@torch.inference_mode()
def generate(self, prompt, negative_prompt=None, width=1024, height=1024, steps=30, guidance_scale=3.5, seed=None):
g = None
if seed is not None and torch.cuda.is_available():
g = torch.Generator(device="cuda").manual_seed(seed)
out = self.pipe(
prompt=prompt,
negative_prompt=negative_prompt,
width=width,
height=height,
num_inference_steps=steps,
guidance_scale=guidance_scale,
generator=g,
).images[0]
buf = io.BytesIO()
out.save(buf, format="PNG")
return buf.getvalue()
_engine = None
def get_engine():
global _engine
if _engine is None:
_engine = DiffusersEngine()
return _engine
8. 我怎么跑起来:构建、启动、请求一气呵成
# 构建镜像
docker build -t sd35-fp8-mirror:0.1 .
# 启动(把 HF 缓存挂出来,避免重复下载)
docker run --gpus all --rm \
-p 8000:8000 \
-v $PWD/cache:/cache \
sd35-fp8-mirror:0.1
调用:
curl -X POST "http://localhost:8000/v1/txt2img" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A cinematic photo of a rainy neon street, ultra-detailed, 35mm",
"negative_prompt": "blurry, low quality, watermark",
"width": 1024,
"height": 1024,
"steps": 30,
"guidance_scale": 3.5,
"seed": 42
}' --output out.png
9. FP8 / TensorRT 我怎么接(我把它当“第二阶段强化”)
如果我把镜像推到生产环境,我会优先对齐官方 TensorRT 路线,因为 HF 的 TensorRT 仓库已经把关键步骤(容器、脚本、引擎参数、HF Token)写清楚了,并明确存在 --fp8 这条推理分支。(huggingface.co)
我通常会这么做取舍:
- 先用 Diffusers 版把业务链路跑通(API、鉴权、队列、监控)
- 再把 Worker 替换成 TensorRT FP8 引擎(吞吐、显存、稳定性)
- 镜像层保持不变,只替换推理后端实现
10. 我最后的总结
这次“AI 镜像开发”的核心,不是堆参数、也不是追榜单,而是把 SD3.5 FP8 这件事做成一个可以复用的工程模块:
- 镜像解决“环境一致性”
- FP8/TensorRT 解决“性能与显存”(Stability AI)
- API 化解决“可集成与可上线”
参考链接(方便我贴到 CSDN 参考区)
Stability AI:Introducing Stable Diffusion 3.5
https://stability.ai/news/introducing-stable-diffusion-3-5
Hugging Face:stabilityai/stable-diffusion-3.5-large
https://huggingface.co/stabilityai/stable-diffusion-3.5-large
Hugging Face:stabilityai/stable-diffusion-3.5-large-tensorrt
https://huggingface.co/stabilityai/stable-diffusion-3.5-large-tensorrt
Diffusers 文档:Stable Diffusion 3 Pipeline(3 encoders / offloading)
https://huggingface.co/docs/diffusers/main/en/api/pipelines/stable_diffusion/stable_diffusion_3
Stability AI:SD3.5 TensorRT + FP8 官方公告
https://stability.ai/news/stable-diffusion-35-models-optimized-with-tensorrt-deliver-2x-faster-performance-and-40-less-memory-on-nvidia-rtx-gpus
(可选)我给自己留的“技术自测题”
- SD3 pipeline 为什么会用 三个文本编码器?这对显存与加载时间意味着什么?(huggingface.co)
- 我把 Diffusers Worker 切到 TensorRT FP8 Worker 时,镜像层和服务层分别应该改哪里、哪些不该动?(huggingface.co)
- 公开信息里提到的“更快 + 更省显存”,在工程上应该如何量化(吞吐、p95 延迟、显存峰值、冷启动时间)?(Stability AI)
更多推荐

所有评论(0)