ComfyUI 是近來持續熱門的地端 AI 優秀方案,專門出圖出影片,很多人會把幾百 GB 的模型庫放在 NAS 上,透過 NFS 或 SMB 來給有 GPU 顯示卡的裝置存取載入。如果你在 NAS 上有安裝顯卡,或者是買了 QNAP AI NAS 的話,該怎樣在上面跑這個呢 ? CyberQ 實作記錄把 ComfyUI 0.34.3 部署到 QNAP NAS 的過程,包含給大家通用版本的 Container Station 的 compose stack、實測的出圖時間與 VRAM 峰值,以及沿路碰到的一堆問題解法。
最後,我們也整理了 2026 年地端出圖的模型選型與量化實測,重點結論和具備較大 VRAM 顯示卡上的直覺相反。
目標與測試硬體
| 項目 | 規格 |
|---|---|
| 機型 | QNAP TS-855X |
| CPU | Intel Atom C5125(Tremont 核心) |
| 記憶體 | 64 GB |
| GPU | NVIDIA RTX A2000 12GB(sm_86)/ 約等同於 RTX 3600 12GB (但省電一半以上,最高峰值 70W vs 170W) |
| 驅動程式版本 | 575.64.05,對應 CUDA 12.9 |
| 模型庫 | /share/Public 底下既有 555 GB |
目標很單純,ComfyUI 直接讀 NAS 上既有的模型庫,不搬檔也不複製,並且能透過 App Center 安裝與啟停,可參考實測用到的一組 Container Station compose stack 範例協助你自己手動實作完成。
部署結果一覽
ComfyUI v0.34.3 在這套 NAS 加 NVIDIA 顯示卡上可正常運作,服務位址為 http://<NAS_IP>:8188。實際跑圖片的時候,會用掉大部分的 VRAM 記憶體,GPU溫度也會上升,如果你的模型太大,就會再多用掉系統記憶體來完成推論。

| 項目 | 值 |
|---|---|
| 映像 | comfyui-nas:0.34.3,9 GB |
| torch | 2.9.1+cu128 |
| GPU 直通 | runtime 指定 nvidia-runtime,環境變數 NVIDIA_VISIBLE_DEVICES 與 NVIDIA_DRIVER_CAPABILITIES |
| DynamicVRAM | 已啟用(comfy-aimdo 0.4.15) |
| 資料目錄 | /share/Container/comfyui(實體路徑 /share/ZFS18_DATA/Container/comfyui) |
torch 版本要特別留意。驅動 575.64.05 對應的是 CUDA 12.9,因此只能用 cu128 的 wheel,cu130 在這台機器上不能用。
動手之前,先認識某些 NAS 的限制
這一節建議在開始之前先讀完,多數問題都出在這裡,而且大部分在安裝階段完全看不出來。
如果 CPU 沒有 AVX,原生擴充套件會直接炸
Atom C5125 的指令集只到 sse4_2,完全沒有 AVX,這是這類採用 Atom 處理器的機器最大隱藏限制,如果你的 NAS 採用更高規格的 Intel 處理器或 AMD 處理器,就沒這問題,比方說 QAI-h1290FX,這台除了地端 AI 推論,如果做 AI 出圖和 AI 產影片工作站也會非常強大,是本文範例中機器無法比擬的。
一個碰到產生程式錯誤的實際案例是 kornia_rs。從 0.1.13 起的 wheel 帶了這顆 CPU 執行不了的指令,import 時直接噴錯誤 Fatal Python error: Illegal instruction。更麻煩的是它在 ComfyUI 載入 comfy_extras/nodes_post_processing.py 時才發作,pip 安裝階段一切正常。實測 0.1.10 以下可以用,所以這必須在 Dockerfile 中釘死。
因此在這台 NAS 上安裝任何帶原生擴充的 Python 套件,都要先確認 wheel 的指令集需求。
系統工具短缺
QuTS Hero上沒有 git、沒有 nohup,也沒有 scp 或 sftp。CyberQ 對應做法如下。
取原始碼用 curl 抓 tarball
背景執行用 setsid
傳檔用 ssh nas 'cat > 目標檔' < 本機檔
另外 readlink 在 /usr/bin 而非 /bin。腳本若寫成 /bin/readlink 又把 stderr 丟掉,就會安靜地退回 fallback 路徑,表面上看起來一切正常。
docker CLI 需要可寫的 HOME
docker CLI 需要 HOME 與 DOCKER_CONFIG 指到可寫路徑,否則會在 container-station/homes/ 底下踩到 permission denied 權限問題。
路徑一律用實體路徑
/share 是 tmpfs,/share/Container 與 /share/Public 都是符號連結。compose 的 volume 掛載一律寫實體路徑,例如 /share/ZFS18_DATA/Container/comfyui,由於每個人的機器設定都不太一樣,那個實體路徑你要去自己從 NAS 中抓出來,透過 SSH 連線進去看是最快且正確的了。
開機時序
開機後這台機器上的 NVIDIA 核心模組要到第 345 秒左右才載入,dockerd 更晚。因此請有耐心地等一下之後,再來開容器,不然 ComfyUI 會失效不能用。
部署重點
容器的映像建置
我們可以使用 QNAP 的容器工作站 Container Staion,要使用 Dockerfile 的三個關鍵決定如下。
torch、torchvision、torchaudio 三件套必須一起釘版本。只釘 torch 的話,pip 會把 torchaudio 解到 2.11.0,與 torch 2.9.1 的 ABI 不相容,錯誤訊息是 undefined symbol: torch_library_impl。
kornia_rs 釘在 0.1.10 以下,原因見上一節。這個實作會使用 cu128 的 wheel index。
DOCKERFILE compose 設定
# 示意,路徑請換成自己的實體路徑,你手上的機器會不同要先查,這是測試過的可用配方
services:
comfyui:
build:
context: .
args:
COMFY_REF: v0.34.3
TORCH_INDEX: https://download.pytorch.org/whl/cu128
TORCH_VERSION: 2.9.1+cu128
TORCHVISION_VERSION: 0.24.1+cu128
TORCHAUDIO_VERSION: 2.9.1+cu128
dockerfile_inline: |
FROM python:3.12-slim-bookworm
ARG COMFY_REF=v0.34.3
ARG TORCH_INDEX=https://download.pytorch.org/whl/cu128
ARG TORCH_VERSION=2.9.1+cu128
ARG TORCHVISION_VERSION=0.24.1+cu128
ARG TORCHAUDIO_VERSION=2.9.1+cu128
ENV DEBIAN_FRONTEND=noninteractive \
PIP_NO_CACHE_DIR=1 \
PYTHONUNBUFFERED=1 \
PATH=/opt/venv/bin:$$PATH
RUN apt-get update && apt-get install -y --no-install-recommends \
git ca-certificates curl tini \
libgl1 libglib2.0-0 libgomp1 \
&& rm -rf /var/lib/apt/lists/*
RUN python -m venv /opt/venv
RUN pip install --no-cache-dir --index-url "$${TORCH_INDEX}" \
"torch==$${TORCH_VERSION}" \
"torchvision==$${TORCHVISION_VERSION}" \
"torchaudio==$${TORCHAUDIO_VERSION}"
RUN curl -fsSL "https://codeload.github.com/comfyanonymous/ComfyUI/tar.gz/refs/tags/$${COMFY_REF}" \
-o /tmp/comfyui.tar.gz \
&& mkdir -p /opt/ComfyUI \
&& tar -xzf /tmp/comfyui.tar.gz --strip-components=1 -C /opt/ComfyUI \
&& rm -f /tmp/comfyui.tar.gz \
&& mkdir -p /opt/defaults/custom_nodes \
&& cp /opt/ComfyUI/custom_nodes/* /opt/defaults/custom_nodes/ 2>/dev/null || true
RUN grep -vE '^(torch|torchvision|torchaudio)([=<>!~[]|$$)' /opt/ComfyUI/requirements.txt > /tmp/req.txt \
&& pip install --no-cache-dir -r /tmp/req.txt \
&& python -c "import comfy_aimdo.control, comfy_kitchen; print('aimdo/kitchen import OK')"
RUN pip install --no-cache-dir "kornia_rs==0.1.10" \
&& python -c "import kornia, kornia_rs; print('kornia', kornia.__version__, 'with kornia_rs', kornia_rs.__version__, 'OK')"
COPY <<'YAML' /opt/defaults/extra_model_paths.yaml
shared_models:
base_path: /models/public/
is_default: true
diffusion_models: |
unet/
diffusion_models/
text_encoders: |
clip/
text_encoders/
vae: vae/
loras: loras/
controlnet: controlnet/
clip_vision: clip_vision/
embeddings: embeddings/
upscale_models: upscale_models/
style_models: style_models/
model_patches: model_patches/
configs: configs/
local_models:
base_path: /models/local/
diffusion_models: diffusion_models/
text_encoders: text_encoders/
vae: vae/
loras: loras/
unet_gguf: unet/
clip_gguf: clip/
YAML
COPY <<'SCRIPT' /usr/local/bin/entrypoint.sh
set -e
CONFIG_DIR="$${CONFIG_DIR:-/config}"
MODEL_PATHS="$$CONFIG_DIR/extra_model_paths.yaml"
mkdir -p "$$CONFIG_DIR"
if [ ! -f "$$MODEL_PATHS" ]; then
cp /opt/defaults/extra_model_paths.yaml "$$MODEL_PATHS"
echo "[entrypoint] wrote a default $$MODEL_PATHS, edit it on the NAS and restart"
fi
if [ -d /opt/ComfyUI/custom_nodes ] && [ -z "$$(ls -A /opt/ComfyUI/custom_nodes 2>/dev/null)" ]; then
cp /opt/defaults/custom_nodes/* /opt/ComfyUI/custom_nodes/ 2>/dev/null || true
fi
export PYTHONPATH="/opt/pip-extra:$${PYTHONPATH}"
python - <<'PY' || exit 1
import sys, torch
print("[entrypoint] torch", torch.__version__, "built for CUDA", torch.version.cuda)
if not torch.cuda.is_available():
print("[entrypoint] CUDA unavailable. Check the compose runtime and the NVIDIA_* environment variables.", file=sys.stderr)
sys.exit(1)
cap = torch.cuda.get_device_capability(0)
print("[entrypoint] device", torch.cuda.get_device_name(0), "sm_%d%d" % cap)
if cap < (8, 9):
print("[entrypoint] note: sm_%d%d has no native fp8, so fp8 weights are storage only and are cast for compute." % cap)
if cap < (10, 0):
print("[entrypoint] note: sm_%d%d has no native NVFP4, so nvfp4 weights go through emulated dequantization." % cap)
PY
cd /opt/ComfyUI
echo "[entrypoint] exec main.py $$*"
exec python main.py --extra-model-paths-config "$$MODEL_PATHS" "$$@"
SCRIPT
RUN chmod +x /usr/local/bin/entrypoint.sh
WORKDIR /opt/ComfyUI
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"]
image: comfyui-standalone:v0.34.3
container_name: comfyui
restart: unless-stopped
runtime: nvidia-runtime
environment:
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=compute,utility
- TZ=UTC
ports:
- "8188:8188"
user: "0:100"
mem_limit: 26g
memswap_limit: 50g
shm_size: 2gb
labels:
- "com.centurylinklabs.watchtower.enable=false"
volumes:
# Editable settings. extra_model_paths.yaml is written here on first run.
- /share/CACHEDEV1_DATA/Container/comfyui/config:/config
- /share/CACHEDEV1_DATA/Container/comfyui/custom_nodes:/opt/ComfyUI/custom_nodes
- /share/CACHEDEV1_DATA/Container/comfyui/user:/opt/ComfyUI/user
- /share/CACHEDEV1_DATA/Container/comfyui/pip-extra:/opt/pip-extra
- /share/CACHEDEV1_DATA/Container/comfyui/output:/output
- /share/CACHEDEV1_DATA/Container/comfyui/input:/input
- /share/CACHEDEV1_DATA/Container/comfyui/temp:/temp
- /share/CACHEDEV1_DATA/Container/comfyui/models-local:/models/local
# Your model library, read only. Point this wherever you keep weights.
- /share/CACHEDEV1_DATA/Public/models:/models/public:ro
command:
- --listen
- "0.0.0.0"
- --port
- "8188"
- --output-directory
- /output
- --input-directory
- /input
- --temp-directory
- /temp
- --reserve-vram
- "0.5"排錯紀錄,CUDA 完全無法初始化
這個問題會單獨列出來,因為它與容器設定無關,任何 GPU 工作負載都可能遇到。這個 bug 的症頭,是 cuInit 回傳 CUDA_ERROR_NOT_INITIALIZED,核心日誌出現 NVRM: Cannot allocate sysmem through fb heap。當時 MemFree 還有 15.8 GB,但 /proc/buddyinfo 顯示 Normal zone 的 order-7 以上連續頁面數量是 0。
時間線可以佐證,從 log 看,這款 NAS 的 NVIDIA Driver 驅動在開機後 362 秒載入,第一次失敗在 50107 秒,換句話說開機後頭 14 小時都是好的。因為這時候沒法用,所以決定重開機,重開機後後 order-10 從 0 恢復到 14261 塊,CUDA 隨即可正常使用。
結論是記憶體碎裂會讓 NVIDIA 驅動程式拿不到連續的系統記憶體。NAS 長時間跑著大量容器,碎裂到一定程度後 GPU 就會突然罷工。若遇到同樣症狀,先看 buddyinfo 再決定要不要重開。我們自己的測試案例,確實是重開後就好了沒錯。
實測資料
出圖時間
| 工作 | 組合 | 牆鐘 | 峰值 VRAM |
|---|---|---|---|
| Flux 冷啟 | flux1-krea-dev_fp8_scaled + t5xxl_fp8 + clip_l + ae,1024×1024,20 步 | 250 s | 9265 MiB |
| Flux 暖啟 | 同上,換種子 | 80 s | 9265 MiB |
| Qwen-Image | qwen_image_2512_fp8_e4m3fn + qwen_2.5_vl_7b_fp8 + qwen_image_vae,1024×1024,20 步 | 542 s | 10263 MiB |
實測發現的小細節
Qwen-Image 跑得動
原本在規劃時認為 19 GB 檔案大小的 DiT 模型檔對 12 GB VRAM 加上當時僅 15 GB 可用 RAM 不可行。實際在清出記憶體後成功出圖,542 秒,沒有 OOM 記憶體爆掉的錯誤。這是因為,ComfyUI 的 DynamicVRAM 技術會自動把模型權重分層串流,VRAM 在這樣的情況下就不是主要限制,反而是可用的系統 RAM 容量才是上限。因此 GGUF 量化目前只是加速手段,還沒有到必要條件。
VRAM 較小的顯示卡,其瓶頸順序是 RAM 先於 VRAM。 執行 Qwen-Image 時 MemAvailable 從 55 GB 掉到 6.4 GB。要跑大模型的話,NAS 上就不能同時擠滿其他容器,這樣記憶體會不夠用。
2026 年地端出圖模型怎麼選
最佳推薦
依 2026 年我們使用到現在的實際體感和測試,Krea 2 與 Ideogram 4.0 是目前最強的兩個地端模型,Flux.2 與 Qwen-Image 2.0 則構成可搭配使用的優秀模型。CyberQ 建議的分工大致如下。
Krea 2 勝在寫實感與風格,較少「預設 AI 味」
Ideogram 4 勝在圖中文字排版
Qwen-Image 勝在中英文字渲染
Flux.2 Klein 勝在小而快,且採 Apache 2.0 授權
在使用上,授權要特別注意,Krea 2 採社群授權,年營收 100 萬美元以下且 50 席以內才可免費商用。Qwen-Image 2.0 與 Flux.2 Klein 則採用 Apache 2.0,沒有這個限制。
缺的通常是 text encoder
本次實作中,本機模型庫其實已經有 krea2、ideogram4、z-image、flux-2-klein 的 DiT,對應的 text encoder 為必要下載項目,是很多人會踩到的問題,這邊先列表說明一下。
| 模型 | 需要的 TE | 通常狀況 |
|---|---|---|
| Krea 2 | Qwen3-VL-4B(多模態) | 預設可用的版本 |
| Ideogram 4 | Qwen3-8B(純文字路徑)或 Qwen3-VL-8B | qwen_3_8b_fp8mixed 可用 |
| Z-Image | Qwen3-4B(純文字) | qwen_3_4b 檔案較小 |
| Flux.2 Klein | Mistral-3-Small 或 Qwen3-VL | mistral_3_small_flux2_fp8 16.8 GiB,偏大 |
判斷依據是 comfy/sd.py 的 detect_te_model()。它靠 model.visual.merger.linear_fc2.weight 的 shape 分辨 4B 與 8B。本機原有的 qwen_3_4b 與 qwen_3_8b_fp8mixed 都沒有 visual 權重,屬於純文字版,無法拿來跑 Krea 2。
要使用 Krea2 ,需要下載的 text encoder 檔案來自官方 Comfy-Org/Krea-2。
text_encoders/qwen3vl_4b_fp8_scaled.safetensors,5,242,467,968 位元組
diffusion_models/krea2_turbo_nvfp4.safetensors,7,673,668,448 位元組
本機原有的 krea2_turbo_int8_convrot.safetensors 為 13,492,686,496 位元組,與官方檔案位元組數一致。VAE 用的 qwen_image_vae.safetensors 也已下載好。
量化實測,塞得進 VRAM 比原生算子重要
Krea 2 Turbo,1024×1024、8 步、cfg 1.0、euler/simple,同一組種子 seed。
| DiT 變體 | 檔案大小 | 冷啟 | 暖啟 | 峰值 VRAM | 算子路徑 |
|---|---|---|---|---|---|
| int8_convrot | 12.57 GiB | 228 s | 100 s | 7725 MiB | native |
| nvfp4 | 7.15 GiB | 84 s | 56 s | 9227 MiB | emulated |
nvfp4 比 int8 快 1.79 倍,儘管 nvfp4 在 sm_86 上是模擬的,int8 是原生的。ComfyUI 啟動時印出的算子支援如下。
Native ops: int8_tensorwise, asym_w4a8_int8, convrot_w4a4
emulated ops: float8_e4m3fn, nvfp4, mxfp8, float8_e5m2原因在 VRAM 容量。int8 版 12.57 GiB 超過 A2000 的 11.9 GiB 顯存,DynamicVRAM 只好每一步串流權重。峰值 VRAM 反而更低(7725 對 9227 MiB)就是被串流的證據。nvfp4 版 7.15 GiB 全程常駐,省下的 PCIe 往返遠大於反量化的代價。同種子的兩張圖畫質等價,nvfp4 的品質維持得很好,沒有肉眼可見的顯著損失。

由此得出在 12 GB 卡上選量化版本的準則, DiT 加上活化值要塞進 11.4 GiB,也就是 --reserve-vram 0.5 之後的可用量。其次是量化格式本身的效率,這與在較高 VRAM 顯示卡的直覺相反。
推薦組合
| 用途 | 組合 | 暖啟 |
|---|---|---|
| 寫實照片與風格化(首選) | krea2_turbo_nvfp4 + qwen3vl_4b_fp8_scaled + qwen_image_vae,8 步 | 56 s |
| 通用,生態最完整 | flux1-krea-dev_fp8_scaled + t5xxl_fp8 + clip_l + ae,20 步 | 80 s |
| 中英文字渲染 | qwen_image_2512_fp8 + qwen_2.5_vl_7b_fp8 + qwen_image_vae,20 步 | 542 s(冷啟) |
ComfyUI 官方 Krea 2 主流範本怎麼用
官方列出的兩個 Krea 2 範本選哪一個 ?
image_krea2_turbo_t2i 與 image_krea2_turbo_t2i_int8 除了 UNETLoader 那一個檔案之外完全相同。其餘設定包括 qwen3vl_4b_fp8_scaled TE、qwen_image_vae、krea2_darkbrush LoRA、KSampler 8 步 cfg 1 euler/simple、1024×1024,兩者一致。開範本時看到「只需要 darkbrush」,是因為那顆 int8 DiT 本機早就有,ComfyUI 只列缺的檔案。
| 範本 | DiT | 大小 | 塞得進 11.4 GiB | sm_86 算子 |
|---|---|---|---|---|
| image_krea2_turbo_t2i | krea2_turbo_fp8_scaled | 12.24 GiB | 否 | emulated |
| image_krea2_turbo_t2i_int8 | krea2_turbo_int8_convrot | 12.57 GiB | 否 | native |
| 建議替換 | krea2_turbo_nvfp4 | 7.15 GiB | 是 | emulated |
兩個範本的 DiT 都塞不進這張卡,都會逐步串流權重。fp8 那個更差,既要串流,fp8 在 sm_86 上又是模擬的,int8 至少是原生算子。
建議做法是開 int8 範本(省下 13 GB 的下載),再把 UNETLoader 換成 krea2_turbo_nvfp4,這個檔案就小很多,可以很好地載入。如果你使用的是 QNAP 新的 AI NAS,上面的顯示卡 VRAM 都大很多,前面的大檔案權重模型就可以直接用沒關係。
Krea 2 提供 9個官方風格 LoRA
LoRA 已驗證可以套用在 nvfp4 量化權重上,日誌顯示 263 patches attached。以 krea2_darkbrush 為例,觸發詞 monochrome ink wash style 風格正確生效,含 LoRA 冷啟 70 秒。

| LoRA | 觸發詞 |
|---|---|
| krea2_darkbrush | monochrome ink wash style |
| krea2_dotmatrix | monochrome stippling style |
| krea2_kidsdrawing | naive expressive sketch style |
| krea2_neondrip | textured abstract style |
| krea2_rainywindow | rainy window style |
| krea2_retroanime | purple retro anime style |
| krea2_softwatercolor | art deco watercolor style |
| krea2_sunsetblur | ethereal motion blur style |
| krea2_vintagetarot | vintage tarot style |
建議強度皆為 1.0,範本 widget 預設 0.8。範本另有 prompt_enhance 的 LLM 提示詞擴寫模組與 enable_lora 開關,兩者都在子圖左側以 Feature Switch 控制。九顆 LoRA 每顆 469,291,992 位元組、528 個張量。


圖像風格參考(image style reference)範本
krea2_style_reference.safetensors(457,111,760 位元組、512 個張量,metadata 標記 ss_base_model_version: krea2,由 ai-toolkit 0.10.20 訓練)對應範本 image_krea2_turbo_int8_image_style_reference。
這條管線與純文字生圖差很多,不是換掉 LoRA 就好。
UNETLoader -> LoraLoaderModelOnly(krea2_style_reference, 1.0) -> ModelSamplingFlux(1.15, 0.5, 1024, 1024)
CLIPLoader(krea2) + VAELoader + LoadImage(參考圖 1 至 3 張)
-> TextEncodeQwenImageEditPlus(clip, vae, image1..3, prompt)
-> FluxKontextMultiReferenceLatentMethod(index_timestep_zero)
-> CFGGuider(cfg 1) 搭 ConditioningZeroOut 當負向
BasicScheduler(simple, 8 步, denoise 1) + KSamplerSelect(euler) + RandomNoise
-> SamplerCustomAdvanced -> VAEDecode三個重點差異如下。
取樣改用 SamplerCustomAdvanced 而非 KSampler
模型要多過一層 ModelSamplingFlux
提示詞編碼改用 TextEncodeQwenImageEditPlus,它同時吃 clip、vae 與最多三張參考圖
實測以 nvfp4 DiT,參考圖用先前生成的水墨閘門,提示詞改成完全不同的主體「燈塔」,120 秒完成,256 patches attached,風格正確轉移。範本本身沒有附參考圖,krea2_reference_image.png 要自己放進 input/。同樣建議把 UNETLoader 從範本預設的 int8 換成 nvfp4。
CyberQ 觀點
這次部署中,實測有幾個要留意的點。
在某些處理器版本的 NAS 上安裝任何帶原生擴充的套件,先確認指令集,Atom C5125 沒有 AVX。
extra_model_paths.yaml 的 is_default: true 會反轉搜尋順序,且不會告警,模型解析錯了很難發現。
記憶體碎裂會讓 CUDA 完全無法初始化,與容器設定無關,看 buddyinfo 即可判斷。
12 GB 顯示卡上選量化版本,先看塞不塞得進 VRAM,再看算子是否原生。nvfp4 在 sm_86 是模擬的,卻比原生 int8 快 1.79 倍。
以上本文圖片均由 NAS 上的 ComfyUI 地端 AI 實測完成











