用 Docker 部署 Ollama 与 Open WebUI 搭建本地大模型
在 NAS 或 Linux 服务器上用 Docker 跑起本地大模型,含显存测算、模型选型、部署步骤与性能调优
1 序言
用别人的 API 有两个绕不开的问题:一是数据要出内网,你问的任何东西都会先经过人家服务器;二是按量计费,用得多了心慌。
而家里那台常年开机的 NAS,其实已经具备跑大模型的条件——只要它能跑 Docker。本文记录我在 Debian 12 / 飞牛 OS 上用 Docker 部署 Ollama(推理服务) + Open WebUI(网页对话界面) 的完整过程,重点解决三个问题:
- 我这台机器到底能跑多大的模型(第二章先算硬件账,别装完才发现跑不动);
- 怎么用 docker-compose 一次装好(第三、四章);
- 怎么让速度可接受(第六章,默认参数下 GPU 利用率往往只有一半)。
全程只用到 Docker,不需要编译、不需要装 Python 环境。
2 先算硬件账
这一步别跳过。很多人部署失败不是命令写错,是模型选大了。
2.1 三条硬指标
跑大模型只看三样东西:显存、内存、磁盘。
- 显存:决定模型能不能跑在 GPU 上。放不下就会自动降级到 CPU,速度掉一个数量级。
- 内存:CPU 推理时模型权重全部加载到内存;GPU 推理时也需要内存存放 KV Cache 的溢出部分。
- 磁盘:模型文件体积,通常是显存的 1.2 倍左右。
2.2 显存怎么估
一个够用的经验公式:
显存需求 ≈ 参数量(亿) × 量化位数 ÷ 8 (GB) + KV Cache 余量
以 Q4 量化(4 bit)为例,各规格的参考值:
| 模型参数 | Q4 量化显存 | 模型文件大小 | 运行内存建议 |
|---|---|---|---|
| 1.5B | 约 1.5 GB | 约 1 GB | 4 GB |
| 7B / 8B | 约 5 GB | 约 4.7 GB | 8 GB |
| 14B | 约 9 GB | 约 9 GB | 16 GB |
| 32B | 约 20 GB | 约 19 GB | 32 GB |
| 70B | 约 40 GB | 约 40 GB | 64 GB |
必须留余量。上表是「刚好装下」的数,实际还要给 KV Cache(上下文越长占用越大)和系统留 1–3 GB。所以 8 GB 显存跑 7B/8B 是舒服的,跑 14B 就会爆。
2.3 三种部署形态
| 部署形态 | 典型硬件 | 7B 模型速度预期 | 适合什么 |
|---|---|---|---|
| 纯 CPU | 无独显,普通 x86 | 2–5 tokens/s | 偶尔问答,能接受慢 |
| 核显 / 小主机 | Intel N100、ARM 盒子 | 3–8 tokens/s | 轻量问答、翻译 |
| 独立显卡 | RTX 3060 12G 及以上 | 30–80 tokens/s | 日常主力,体验接近在线服务 |
我自己的建议:核显和纯 CPU 只适合「能用就行」的场景。如果你打算天天用,一张 12G 显存的二手卡(如 3060 12G)性价比最高,7B、8B、14B 都能舒服跑。
3 部署 Ollama
Ollama 负责加载模型、对外提供 API,是整套方案的引擎,默认监听 11434 端口。
3.1 前置:NVIDIA 显卡需装容器工具包
只有用 NVIDIA 独显 才需要这一步,核显和纯 CPU 跳过。
# 添加 NVIDIA 容器工具包源
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
| sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt update
sudo apt install -y nvidia-container-toolkit
sudo systemctl restart docker
装完先验证宿主机能识别显卡:
nvidia-smi
只要能看到显卡型号和显存占用表,就说明驱动正常。
3.2 docker-compose.yaml
我沿用「yaml 文件与数据分开」的目录习惯,路径建在 /docker/apps/docker-compose/ 下:
mkdir -p /docker/apps/docker-compose/ollama
cd /docker/apps/docker-compose/ollama
新建 docker-compose.yaml:
# 官方文档
# https://hub.docker.com/r/ollama/ollama
# https://github.com/ollama/ollama
---
name: ollama
# 最后编辑时间:2026-09-23
services:
ollama:
# 镜像地址
image: ollama/ollama:latest
# 容器名
container_name: ollama
# 主机名
hostname: ollama
# 调用宿主机 GPU(无独显请整段删除)
gpus: all
volumes:
# 模型与配置持久化,重装容器不丢模型
- /docker/apps/ollama:/root/.ollama
environment:
# 时区
TZ: Asia/Shanghai
# 模型在显存中空闲驻留时长,-1 表示不卸载
OLLAMA_KEEP_ALIVE: "30m"
# 单模型最大并行请求数,显存小的机器保持 1
OLLAMA_NUM_PARALLEL: "2"
# 同时常驻显存的模型数量上限
OLLAMA_MAX_LOADED_MODELS: "1"
ports:
# API 端口,局域网内其他设备也靠它调用
- 11434:11434
# 重启策略,总是重启
restart: always
启动:
# 拉取镜像并后台启动
docker compose pull && docker compose up -d
# 查看日志,确认没有报错
docker compose logs -f ollama
⚠️ 没有独显的机器务必删掉
gpus: all这一行,否则容器会启动失败并提示找不到 GPU。
3.3 验证
# 看容器状态,STATUS 应为 Up
docker ps | grep ollama
# 拉一个小模型测试(首次会下载约 1GB)
docker exec -it ollama ollama pull qwen2.5:1.5b
# 命令行直接对话,输入 /bye 退出
docker exec -it ollama ollama run qwen2.5:1.5b
到这里 Ollama 已经能用了,只是个命令行。下面给它配个网页界面。
4 部署 Open WebUI
Open WebUI 是一个自托管的对话前端,界面接近 ChatGPT,支持多模型切换、对话历史、文件上传,并且默认就能对接 Ollama。
4.1 docker-compose.yaml
mkdir -p /docker/apps/docker-compose/open-webui
cd /docker/apps/docker-compose/open-webui
新建 docker-compose.yaml:
# 官方文档
# https://github.com/open-webui/open-webui
# https://docs.openwebui.com
---
name: open-webui
# 最后编辑时间:2026-09-23
services:
open-webui:
# 镜像地址,CPU 机器可选 :main,追求体积可换 :main-slim
image: ghcr.io/open-webui/open-webui:main
# 容器名
container_name: open-webui
# 主机名
hostname: open-webui
# 🔴 关键:使用 host 网络,容器与宿主机共享网络栈
# 好处是能直接通过 127.0.0.1 访问 Ollama,无需额外建网络
# 注意:host 模式下 ports 段会被忽略,WebUI 默认监听 8080,直接访问宿主 IP 即可
network_mode: host
environment:
# 时区
TZ: Asia/Shanghai
# 🔴 关键:告诉 Open WebUI 去哪找 Ollama
# host 网络下走本机地址;若两者在自定义 bridge 网络里,则填 http://ollama:11434
OLLAMA_BASE_URL: http://127.0.0.1:11434
# 关闭首次启动的联网检查,内网环境更快
OFFLINE_MODE: "true"
# 首次访问自动创建的账号(不设则第一个注册的人成为管理员)
# WEBUI_AUTH: "false"
volumes:
# 数据持久化(用户、对话、配置)
- /docker/apps/open-webui:/app/backend/data
# 重启策略,总是重启
restart: always
启动:
docker compose pull && docker compose up -d
4.2 首次登录
浏览器打开 http://你的内网IP:8080。
- 第一个注册的账号自动成为管理员,注册后建议在「设置 → 管理员设置」里关掉公开注册。
- 进入后左上角能看到模型列表。如果列表是空的,说明没连上 Ollama,回到 7.1 排查。
- 中文界面:右上角头像 → Settings → General → Language,选「简体中文」。
5 模型选择与拉取
5.1 中文场景的实用组合
| 用途 | 推荐模型 | 拉取大小 | 建议显存 |
|---|---|---|---|
| 日常问答、写作 | qwen2.5:7b | 约 4.7 GB | 8 GB |
| 强推理、数学 | deepseek-r1:8b | 约 5 GB | 8 GB |
| 轻量问答、翻译 | qwen2.5:3b | 约 2 GB | 4 GB |
| 文字向量(RAG 用) | bge-m3 | 约 1.2 GB | 4 GB |
中文场景优先选 Qwen 系。同一参数量下,Qwen 的中文表达和指令遵循明显优于 Llama,这是实测结论不是偏好。
5.2 常用命令
# 拉取模型
docker exec -it ollama ollama pull qwen2.5:7b
# 列出本地已有模型
docker exec -it ollama ollama list
# 删除模型(释放磁盘)
docker exec -it ollama ollama rm qwen2.5:1.5b
# 查看某个模型占了多少显存
docker exec -it ollama ollama ps
拉取完成后回到 Open WebUI 刷新页面,模型就会出现在左上角下拉框里。
6 性能调优
默认参数下 GPU 利用率往往只有一半,调整下面三项能明显提速。
6.1 让模型常驻显存
OLLAMA_KEEP_ALIVE 控制模型空闲多久后从显存卸载。默认 5 分钟,意味着你每聊几句就要重新加载一次(7B 模型加载约 5–10 秒)。改成 30m 或 -1:
environment:
OLLAMA_KEEP_ALIVE: "-1" # 永不卸载,显存充足时最快
代价:模型会一直占着显存。如果机器还要跑别的吃显存的活(比如相册缩图、转码),建议设
30m折中。
6.2 上下文长度
上下文越长,KV Cache 占用越大。Open WebUI 里可以在「设置 → 高级参数」调 num_ctx:
| num_ctx | 7B 模型额外显存 | 适合 |
|---|---|---|
| 2048 | 约 0.5 GB | 短问答,最省 |
| 4096 | 约 1 GB | 默认,日常够用 |
| 8192 | 约 2 GB | 长文档、代码 |
| 32768 | 约 8 GB | 长文总结,8G 显存跑不动 |
6.3 实测参考
在我的环境(RTX 3060 12G,7B Q4)实测:
| 配置 | 首字延迟 | 生成速度 |
|---|---|---|
| 默认(keep_alive 5m,num_ctx 2048) | 8–10 s(含加载) | 约 45 tokens/s |
| keep_alive -1,num_ctx 2048 | < 1 s | 约 48 tokens/s |
| keep_alive -1,num_ctx 8192 | < 1 s | 约 38 tokens/s |
结论:首字延迟的差距几乎全部来自模型加载。常驻显存是收益最大的一项调整。
7 常见问题
7.1 容器里看不到 GPU
现象:日志出现 no CUDA-capable device 或 nvidia-smi 报错。
排查顺序:
- 宿主机
nvidia-smi是否正常(不正常是驱动问题,与 Docker 无关); - 是否装了
nvidia-container-toolkit并重启过 Docker; - compose 里是否写了
gpus: all; - 飞牛 OS 等定制系统可能需要在应用中心额外启用 GPU 支持。
7.2 爆显存 / 速度突然掉到个位数
现象:日志出现 CUDA out of memory 或速度骤降。
原因通常是模型没完全放进显存,Ollama 自动把部分层分给了 CPU。用 ollama ps 查看,正常应显示 100% GPU:
docker exec -it ollama ollama ps
如果显示 xx%/xx% CPU/GPU,说明显存不够:换更小的量化版本(如 qwen2.5:7b-instruct-q4_K_M)、降低 num_ctx,或者减少 OLLAMA_MAX_LOADED_MODELS。
7.3 输出被截断 / 答到一半停了
一般是上下文窗口被占满。调大 num_ctx,或者开一个新对话(历史越长占用越多)。Open WebUI 可以在「设置 → 通用 → 请求」里限制携带的历史消息条数。
7.4 局域网其他设备访问不了
11434(Ollama)和 8080(Open WebUI)都要在宿主机放行。在 Open WebUI 的「管理员设置 → 连接」里把 Ollama 地址改成宿主机内网 IP(如 http://192.168.x.x:11434),这样手机、平板都能用同一个入口。
想让它在外网也能访问?不要直接把端口转发出去。用 Lucky 反代加一层认证,具体做法见同目录的另一篇《用 New API 搭建统一 LLM 网关与 Lucky 反代外网访问》。
8 总结
- 先算显存再选模型,8 GB 显存是「舒服跑 7B/8B」的门槛,别无脑上 14B。
- Ollama 管推理、Open WebUI 管界面,两个容器各司其职,加起来不到 10 行 compose。
- 收益最大的调优是
OLLAMA_KEEP_ALIVE,它直接决定你每次提问要不要等 10 秒。 - 本地部署的价值在隐私和离线,不在省钱。追求能力上限还是得用在线模型,两者不冲突——用网关把它们统一起来即可。
Created with ❤️ by 张萌萌
用 Docker 部署 Ollama 与 Open WebUI 搭建本地大模型
https://blog.nw177.cn/blog/10-技术专栏/50-AI/01.用-Docker-部署-Ollama-与-Open-WebUI-搭建本地大模型分享文章
生成精美分享图或复制链接,与更多人分享本文。