开始之前
需要带 Compose v2 的 Docker Engine —— 也就是 `docker compose` 子命令,而不是旧的 `docker-compose` 可执行文件。要用 GPU 推理还需要 NVIDIA Container Toolkit,正是它让容器能看见显卡;没有它整套服务照样能起来,只是跑在 CPU 上,而且没有任何提示告诉你发生了这件事。
docker compose version # expect v2.x
nvidia-ctk --version # NVIDIA Container Toolkit
# Prove a container can see the GPU before going further:
docker run --rm --gpus=all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smicompose 文件
两个服务:Ollama 负责存放模型并提供 API,Open WebUI 是与之通信的浏览器前端。两者都挂命名卷,否则你第一次重建容器时就要重新下载几十 GB。GPU 预留是最容易被漏掉的那一段。
services:
ollama:
image: ollama/ollama
container_name: ollama
ports:
- "127.0.0.1:11434:11434"
volumes:
- ollama_data:/root/.ollama
restart: unless-stopped
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
ports:
- "127.0.0.1:3000:8080"
environment:
- OLLAMA_BASE_URL=http://ollama:11434
depends_on:
- ollama
volumes:
- webui_data:/app/backend/data
restart: unless-stopped
volumes:
ollama_data:
webui_data:启动并拉取模型
把服务拉起来,然后向运行中的容器拉取模型。按本索引的数字,Llama 3.1 8B 在 Q4_K_M、4K 上下文下需要 5.6 GB,所以对任何 8GB 显卡来说都是一次安全的首拉。注意上面的端口绑定都带了 `127.0.0.1:` 前缀 —— 不加这个前缀,Docker 会发布到所有网络接口,而在很多环境下这会直接绕过主机防火墙。
docker compose up -d
docker exec ollama ollama pull llama3.1:8b
# Then open http://localhost:3000确认它真的跑在 GPU 上
正是这一步把「真正在用 GPU」和「从搭起来那天起就悄悄跑在 CPU 上」区分开。要问容器,而不是问宿主机:在容器里执行 `ollama ps`,它会报告每个已加载模型被放在了哪里。
# Load a model first, then ask where it went:
docker exec ollama ollama run llama3.1:8b "hi" >/dev/null
docker exec ollama ollama ps
# NAME SIZE PROCESSOR UNTIL
# llama3.1:8b 6.1 GB 100% GPU 4 minutes from now
# And from the host, while generating:
nvidia-smi --query-gpu=memory.used,utilization.gpu --format=csv -l 1数字大概该是什么样
GPU 正确直通之后,容器在推理时不应带来明显开销 —— 本站没有实测过容器与原生的对比,但权重反正都在显卡上,上限依然是显卡的显存带宽。Llama 3.1 8B 的 Q4_K_M 权重是 4.6 GB,所以 288 GB/s 的卡生成上限约 62 tok/s,1,008 GB/s 的 RTX 4090 约 218。容器化真正的代价在磁盘:模型卷会随每次 pull 不断增长,而且没有任何东西会替你清理。
docker exec ollama ollama list
docker system df -v | grep ollama_data出问题时
宿主机能正常看到 GPU,但容器内 `ollama ps` 显示 CPU:要么缺了 `deploy.resources.reservations.devices` 那一段,要么没装 NVIDIA Container Toolkit —— 上面那条 `docker run --gpus=all … nvidia-smi` 正是用来区分这两种情况的。`docker compose down` 之后模型消失了:你用的是没能保留下来的 bind mount,或者根本没挂卷;上面那个命名卷才是留住它们的东西。Open WebUI 连不上 Ollama:它必须用服务名 `http://ollama:11434`,不能用 `localhost`,因为在 compose 网络里 `localhost` 指的是 WebUI 容器自己。如果这些端口能被局域网其他机器访问到,检查有没有加 `127.0.0.1:` 前缀 —— 直接发布裸端口会暴露在所有网络接口上。
常见问题
怎么让 Docker 容器用上我的 NVIDIA 显卡?
先在宿主机上安装 NVIDIA Container Toolkit,然后在 compose 的 `deploy.resources.reservations.devices` 中声明设备,写上 `driver: nvidia` 和 `capabilities: [gpu]`。请先用 `docker run --rm --gpus=all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi` 单独验证一次 —— 如果这一步就失败,问题出在工具包上,而不是你的 compose 文件。
同一个 compose 文件里,Open WebUI 为什么连不上 Ollama?
因为容器内的 `localhost` 指的是这个容器自己。请使用服务名:`OLLAMA_BASE_URL=http://ollama:11434`。Compose 会把两个服务放在同一个网络里并自动解析服务名,所以不需要写 IP,也不需要 host 网络模式。
重建容器会丢掉已下载的模型吗?
只有在没用命名卷的情况下才会。`ollama_data:/root/.ollama` 这个映射把模型文件放在容器生命周期之外,所以 `docker compose down` 再 `up` 不会有任何损失。没有它的话你要重新下载几十 GB —— 这也是很多人觉得「本地模型搭起来很慢」的最常见原因。
这篇指南用到了什么
- 格式
- GGUF
接下来
本文涉及的模型
它真的跑起来了吗?
复制命令并不等于它能用,所以站内只在这里问一次。除了你的这个回答之外,不收集任何东西。