NAS玩转本地私有AI:从Ollama+Docker部署到GPU直通与内存分配优化指南

2次阅读
没有评论

共计 3312 个字符,预计需要花费 9 分钟才能阅读完成。

很多极客在家里折腾完影音中心、软路由和内网备份之后,NAS 基本就沦为了一台待机功耗几十瓦的“电费黑洞”。直到今年大模型量化技术(尤其是 GGUF 和 EXL2)成熟,我才彻底找到了这台 NAS 的终极归宿——搭建一个永不断线、不惧隐私泄露的本地私有知识库与 AI 助理。

但真要把大模型塞进 NAS 里,踩坑指数比在普通 PC 上跑高了不止一个量级:Docker 容器内无法识别 Nvidia 显卡驱动、PCIe 直通导致宿主机内核死锁、显存溢出(OOM)触发系统自动杀进程……本文记录我在这台配置为 i5-12400 + RTX 4060Ti 16G + 64GB DDR4 的 TrueNAS SCALE 主机上,从零搭建 Ollama + Open-WebUI 高性能私有化 AI 节点的全过程,包含生产环境级别的防暴毙配置技巧。

一、底层基石:Docker 容器的 GPU 直通与驱动闭坑

在 Linux NAS 环境下调用 GPU,最怕的就是驱动版本不匹配。官方自带的驱动往往落后几个大版本,建议第一步先在 NAS 宿主机底层验证驱动与 CDI (Container Device Interfaces) 是否工作正常。

# 查看宿主机显卡状态,确认驱动版本与 CUDA 支持上限
nvidia-smi

# 检查 nvidia-container-toolkit 是否已正确注册运行时
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi

如果第二条命令报错无法识别 GPU,不要急着重装系统。在大多数基于 Debian/Ubuntu 的 NAS 系统中,通常是缺少了 nvidia-container-runtime 的注册。我们需要手动修正 Docker 的 daemon.json:

{
  "default-runtime": "nvidia",
  "runtimes": {
    "nvidia": {
      "path": "nvidia-container-runtime",
      "runtimeArgs": []}
  }
}

配置完成后,必须执行 systemctl restart docker 重启服务。这一步千万别偷懒,否则后面所有的 Compose 文件都会卡在显卡调度阶段。

二、生产级 Docker Compose 编排:Ollama + Open-WebUI

单容器跑 Ollama 体验很差,我们搭配目前前端生态最成熟的 Open-WebUI。下面是我打磨后的 docker-compose.yml,重点优化了显存保持时间、并发线程以及容器资源隔离。

version: '3.8'

services:
  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    restart: unless-stopped
    ports:
      - "11434:11434"
    volumes:
      - /mnt/fast-pool/appdata/ollama:/root/.ollama
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
      - OLLAMA_KEEP_ALIVE=24h        # 模型常驻显存,避免频繁读取硬盘带来的冷启动延迟
      - OLLAMA_NUM_PARALLEL=2        # 允许双路并发,适合内网多设备请求
      - OLLAMA_FLASH_ATTENTION=1     # 开启闪光注意力机制,大幅节省显存占用
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    restart: unless-stopped
    ports:
      - "3000:8080"
    volumes:
      - /mnt/fast-pool/appdata/open-webui:/app/backend/data
    environment:
      - OLLAMA_BASE_URL=http://ollama:11434
      - WEBUI_SECRET_KEY=generate_your_random_secret_here
      - ENABLE_SIGNUP=false          # 关闭公开注册,确保家庭内网安全性
    depends_on:
      - ollama

几个关键配置细节:

  • 存储路径选择:模型权重(.ollama)千万不要挂载在机械硬盘构成的阵列上!14B 甚至 32B 的模型文件有数十 GB,机械硬盘加载一次模型需要接近一分钟。务必将其放在 NVMe 缓存池中。
  • OLLAMA_FLASH_ATTENTION:针对 Ampere(RTX 30 系)及以上架构显卡,强烈建议开启此参数,长文本处理时显存占用能直接降低 20%~35%。

三、实测调优:上下文溢出与多模型切换排错

系统跑起来后,直接拉取模型进行实测:

# 拉取阿里巴巴开源的 Qwen2.5 14B 量化版
docker exec -it ollama ollama run qwen2.5:14b

我在初次实测长文档问答时遇到了严重的性能雪崩:最初生成速度有 45 tokens/s,但喂入一篇上万字的 PDF 后,速度瞬间暴跌至 4 tokens/s。排查后发现,这是由于 Ollama 默认的上下文窗口配置导致的“显存溢出逃逸”。

默认情况下,Ollama 会根据显存余量自动计算上下文层数。当上下文长度(Context Length)拉满到 32k 甚至 128k 时,KV Cache 挤爆了 16G 显存,导致部分层被动态卸载回了宿主机的系统内存(DDR4),系统不得不反复在 PCIe 总线上搬运数据。

解决方案:为具体模型定制 Modelfile,锁死显存层数与合理的上下文窗口大小:

FROM qwen2.5:14b

# 设置默认上下文长度为 16384,兼顾性能与长度
PARAMETER num_ctx 16384
# 锁定 GPU 卸载层数,绝不允许降级到 CPU
PARAMETER num_gpu 999

通过自定义构建模型:ollama create my-qwen:14b -f ./Modelfile,即使在满负荷长文本下,显卡利用率始终保持在 98% 以上,Tokens 输出速率稳定在 38~42 tokens/s 之间,再也没有出现断崖式下跌。

四、真实性能与选型建议

经过连续一周的高强度实测,基于单张消费级显卡在 NAS 平台上的表现如下:

模型规格 量化级别 显存占用 (8k Context) 推理速度 (Tokens/s) 适用场景
Qwen2.5-7B Q4_K_M ~5.8 GB 78.5 实时翻译、代码补全、低延迟调用
Qwen2.5-14B Q4_K_M ~10.2 GB 41.2 日常逻辑推理、长文本摘要、个人主力
Llama-3.1-8B Q8_0 ~9.1 GB 56.0 英文写作、通用 Agent 工具调度
DeepSeek-Coder-V2-Lite Q4_K_M ~11.5 GB 28.3 复杂逻辑编程与架构设计

对于预算有限的自建 NAS 用户,我不建议盲目追求多卡并行(家庭主板通常没有足够的 PCIe 通道,拆分后 x4 速度会严重限制模型权重传输带宽)。目前 单张 16GB 显存显卡(例如二手的 RTX 3060 12G 或者 4060Ti 16G)是性价比最高的甜点位,配合 Q4/Q5 量化的 14B 级别模型,在家庭场景下可以获得完全不输在线商用 API 的流畅体验。

避坑心得与小结

把大模型落地在 NAS 上,最核心的思想是“服务隔离与资源保活”。最后给打算折腾的朋友三条实操建议:

  1. 慎用休眠插件:如果你的 NAS 配置了硬盘自动休眠或低功耗降频策略,务必将 Ollama 相关进程加入白名单,防止在推理过程中突发休眠导致模型状态丢毁。
  2. 监控显卡温度:NAS 机箱内部通常风道拥挤,显卡在连续进行几轮大上下文处理时功耗会瞬间拉满到峰值,必须通过 IPMI 或宿主机脚本将风扇转速与 GPU 温度关联,否则热降频会让推理性能大打折扣。
  3. API 统一纳管:Open-WebUI 自带标准的 OpenAI 格式路由。在 NAS 上跑通后,你可以直接将宿主机的 http://nas-ip:3000/api 地址分发给家里的 VS Code、沉浸式翻译插件或手机端使用,真正实现一次部署,全端免费私有调用。
正文完
 0
评论(没有评论)