FIELD NOTE / SINGLE ENTRYNO SIGNAL / NO PROBLEM

Ubuntu 部署 Ollama:Docker + NVIDIA GPU 加速(修復 GPU 掉線與模型儲存路徑)

Ollama 是把本地 LLM 包成一個 HTTP API 伺服器的工具:模型下載到本機,跑起來後在 11434 端口提供 OpenAI 相容的介面,任何客戶端都能直接接。這篇從零開始,在 Ubuntu 上用 Docker 部署一個具備 GPU 加速、支援區域網路存取、可自訂模型儲存硬碟、允許多人並發的 Ollama 伺服器。

特別針對兩個常見痛點:「跑一跑 GPU 突然掉線變 CPU」和「Docker 無法識別顯卡」。這兩個問題在一般教學裡常被跳過,但它們正是自架環境最容易卡住的地方。

前置需求

  • Ubuntu 22.04 以上,有 sudo 權限。
  • NVIDIA 顯卡,VRAM 至少 16GB(跑 8B 模型);跑較大模型要更多。
  • NVIDIA driver 550 以上(compute capability 5.0–6.2 的卡需要 570 以上)。
  • Docker 已安裝。
  • 一塊容量足夠的硬碟存放模型——Ollama 的模型動輒幾十 GB,塞系統碟很快爆滿。

開始前先確認顯卡與 driver 真的可用,這一步能省掉後面所有猜測:

nvidia-smi

如果 nvidia-smi 就回不了,先修 driver 再往下走。把 driver 版本和 GPU 型號記下來,之後報錯時可以對照。

步驟一:安裝 NVIDIA Container Toolkit

如果 Docker 啟動時報錯 could not select device driver "" with capabilities: [[GPU]],代表 Docker 缺少 GPU 擴充包——容器看不到顯卡。先加入 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-get update

安裝 Toolkit 並把它註冊成 Docker 的 runtime:

sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

步驟二:修復「跑一跑 GPU 突然掉線變 CPU」

Ollama 閒置一段時間後突然改用 CPU 滿載運算,通常是 Linux 顯卡休眠機制或 Docker cgroup 管理衝突。兩項修復:

A. 開啟 NVIDIA 持久模式。防止顯卡進入深度休眠。建 /etc/systemd/system/nvidia-persistence.service:

[Unit]
Description=NVIDIA Persistence Daemon
Wants=syslog.target
[Service]
Type=forking
ExecStart=/usr/bin/nvidia-smi -pm 1
ExecStop=/usr/bin/nvidia-smi -pm 0
[Install]
WantedBy=multi-user.target
sudo systemctl enable nvidia-persistence.service
sudo systemctl start nvidia-persistence.service

B. 修改 Docker daemon 設定。解決 GPU 發現失敗報錯。/etc/docker/daemon.json 必須包含 exec-opts,注意括號與逗號:

{
  "runtimes": {
    "nvidia": {
      "args": [],
      "path": "nvidia-container-runtime"
    }
  },
  "exec-opts": ["native.cgroupdriver=cgroupfs"]
}
sudo systemctl restart docker

步驟三:自訂模型儲存路徑

預設 Docker 會把模型塞進系統碟。為了避免系統碟爆滿,先在容量較大的硬碟建立專屬資料夾(路徑換成你的實際大容量硬碟):

sudo mkdir -p /media/simon/Storage/ollama_models
sudo chmod 777 /media/simon/Storage/ollama_models

步驟四:啟動 Ollama 容器

若之前有失敗的容器,先 docker rm -f ollama 刪掉,然後執行整段指令:

docker run -d \
  --name ollama \
  --restart always \
  --gpus=all \
  -p 11434:11434 \
  -e OLLAMA_HOST=0.0.0.0 \
  -e OLLAMA_ORIGINS="*" \
  -e OLLAMA_NUM_PARALLEL=8 \
  -v /media/simon/Storage/ollama_models:/root/.ollama \
  ollama/ollama:latest

核心參數解析(必看):

  • --gpus=all:讓容器完整存取 NVIDIA 顯卡。
  • --restart always:容器崩潰或重開機後自動起來。
  • -p 11434:11434:把 API 端口對到主機。
  • -e OLLAMA_HOST=0.0.0.0:開放 API,允許區域網路內其他設備(或 Nginx 反向代理)連入,不限 localhost。
  • -e OLLAMA_ORIGINS="*":解決跨域(CORS),讓 Open WebUI 或 n8n 等外部前端能順利呼叫。
  • -e OLLAMA_NUM_PARALLEL=8:解除單一排隊,允許 8 個請求同時並發。注意:高並發需要較大 VRAM——20GB 顯卡跑 8B 模型設 8 很流暢;跑 35B 這類巨型模型建議拿掉或設 1,以免 OOM 崩潰。
  • -v 實體路徑:/root/.ollama:把容器內的模型下載目錄綁定到步驟三的實體硬碟。

安全提醒:OLLAMA_HOST=0.0.0.0 加上 OLLAMA_ORIGINS="*" 等於把 API 開放給整個區域網路且不限來源。在自家內網可以,但若暴露到公网,至少要加防火牆或反向代理層做認證,否則任何人都能免費用你的 GPU。

步驟五:驗證

先確認容器狀態:

docker ps | grep ollama          # 狀態應為 Up

下載一個小模型測試,跑起來後用 nvidia-smi 看顯卡有沒有真的在算:

docker exec -it ollama ollama run qwen2.5:0.5b

下載完成後去 /media/simon/Storage/ollama_models/models/blobs 檢查,會看到模型實體檔案已經躺在你指定的硬碟裡,而不是系統碟。

最後拿手機或另一台電腦瀏覽器打開 http://<Ubuntu IP>:11434,看到「Ollama is running」就代表區域網路存取也通了。

步驟六:用 API 呼叫

Ollama 有兩套 API。原生 API 是 http://localhost:11434/api:

curl http://localhost:11434/api/chat -d '{
  "model": "qwen2.5:0.5b",
  "messages": [{"role": "user", "content": "why is the sky blue?"}],
  "stream": false
}'

更常用的是 OpenAI 相容端點 /v1/chat/completions,格式跟 OpenAI 完全一樣,只把 hostname 換掉,既有程式不用改:

curl http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen2.5:0.5b",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

Python 端同理,base_url 指到本地伺服器即可(api_key 必填但會被忽略):

from openai import OpenAI
client = OpenAI(base_url="http://localhost:11434/v1/", api_key="ollama")
response = client.chat.completions.create(
    model="qwen2.5:0.5b",
    messages=[{"role": "user", "content": "Say this is a test"}],
)
print(response.choices[0].message.content)

常見坑與收尾

  • 不要亂加第三方 driver PPA。用 distributions 官方或 NVIDIA 支援的 driver 路徑,改 driver 前要有可回退的計畫。
  • GPU 掉線先查持久模式。多數「跑一跑變 CPU」是休眠與 cgroup 衝突,不是模型問題。
  • 並發數要配 VRAM。並發高但 VRAM 不足會 OOM 崩潰,大模型設 1 比較穩。
  • 模型儲存要綁實體硬碟。預設路徑在容器內,系統碟爆滿後要重新掛載很麻煩。

整套跑完之後,你得到的是一台自己掌控的 LLM API 伺服器:模型存在自己的硬碟、GPU 穩定在算、區域網路內任何設備和自動化流程(Open WebUI、n8n)都能直接呼叫。下一步通常是接 Open WebUI 做前端,或把 /v1 端點掛到反向代理後面加認證。

pixel cat

貓說:先讓系統安靜地跑起來。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *