入门Docker 4 分钟阅读发布于 · 更新于

Docker Compose LLM 全家桶:Ollama + Open WebUI

一键部署的 Docker Compose 方案,给你一个本地 ChatGPT 体验。

面向的技术栈

Docker Compose v2 · ollama/ollama · open-webui · 可选 NVIDIA deploy.resources

最近一次修改后未重新实机运行 —— 命令请当作起点,而不是已验证的配方。

DockerOllamaOpen WebUIComposeGGUF

开始之前

需要带 Compose v2 的 Docker Engine —— 也就是 `docker compose` 子命令,而不是旧的 `docker-compose` 可执行文件。要用 GPU 推理还需要 NVIDIA Container Toolkit,正是它让容器能看见显卡;没有它整套服务照样能起来,只是跑在 CPU 上,而且没有任何提示告诉你发生了这件事。

bash
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-smi

compose 文件

两个服务:Ollama 负责存放模型并提供 API,Open WebUI 是与之通信的浏览器前端。两者都挂命名卷,否则你第一次重建容器时就要重新下载几十 GB。GPU 预留是最容易被漏掉的那一段。

yaml
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 会发布到所有网络接口,而在很多环境下这会直接绕过主机防火墙。

bash
docker compose up -d
docker exec ollama ollama pull llama3.1:8b

# Then open http://localhost:3000

确认它真的跑在 GPU 上

正是这一步把「真正在用 GPU」和「从搭起来那天起就悄悄跑在 CPU 上」区分开。要问容器,而不是问宿主机:在容器里执行 `ollama ps`,它会报告每个已加载模型被放在了哪里。

bash
# 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 不断增长,而且没有任何东西会替你清理。

bash
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

接下来

本文涉及的模型

它真的跑起来了吗?

复制命令并不等于它能用,所以站内只在这里问一次。除了你的这个回答之外,不收集任何东西。

相关指南

部署指南仅供学习参考。每个模型均有独立许可协议 — 下载或部署前请阅读 Hugging Face 官方模型卡。