Ollama u Dockeru sa GPU passthrough-om
Kontejner rešava dva problema koja se javljaju čim server prestane da bude samo tvoj: verzija alata više ne zavisi od distribucije, a ceo servis se seli na drugu mašinu jednom komandom. Cena je jedan dodatni sloj koji mora da propusti karticu.
Taj sloj se zove nvidia-container-toolkit i on je sve o čemu ovaj tekst zapravo govori. Bez njega kontejner vidi procesor i ništa više.
Kada u kontejner
| Za | Protiv |
|---|---|
| Verzija alata nezavisna od distribucije | Još jedan sloj koji može da zakaže |
| Ista postavka na svakoj mašini | Slika sa CUDA bibliotekama ide preko gigabajta |
| Više servisa jedan pored drugog, bez sukoba | Drajver i dalje mora biti na domaćinu |
| Vraćanje na staru verziju je trivijalno | Modeli se lako izgube ako volumen nije podešen |
| Prirodan korak ka Kubernetesu | Nešto komplikovaniji nadzor |
Ako imaš jedan server i jedan model, systemd jedinica iz prethodnog teksta je jednostavnija i sasvim dovoljna. Kontejner uzmi kad ti trebaju dva servisa uporedo, kad postavku seliš između mašina, ili kad ideš prema Kubernetesu.
Šta se deli, a šta ne
Ovo je jedina stvar koju treba razumeti pre nego što bilo šta pokreneš.
Domaćin: kernel drajver (nvidia.ko, nvidia_uvm)
↓ propušta se u kontejner
Kontejner: CUDA biblioteke, alat, model
Drajver ostaje na domaćinu i ne instalira se u kontejner. Slika sadrži CUDA biblioteke, a toolkit se stara da uređaj i odgovarajuće biblioteke drajvera budu vidljivi unutra. Zato ista slika radi na mašinama sa različitim verzijama drajvera.
Provera pre svega ostalog:
$ nvidia-smi $ lsmod | grep nvidia_uvm $ docker --version
Ako Docker nemaš, instalacija je opisana u tekstu o instalaciji Dockera.
nvidia-container-toolkit
Debian i Ubuntu:
$ 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
RHEL, Rocky, Fedora:
$ curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo \
| sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo
$ sudo dnf install -y nvidia-container-toolkit
Povezivanje sa Dockerom je zaseban korak — instalacija paketa nije dovoljna:
$ sudo nvidia-ctk runtime configure --runtime=docker $ sudo systemctl restart docker
Komanda upisuje NVIDIA izvršno okruženje u /etc/docker/daemon.json:
$ cat /etc/docker/daemon.json
{
"runtimes": {
"nvidia": {
"args": [],
"path": "nvidia-container-runtime"
}
}
}
Provera
$ docker run --rm --gpus all ubuntu:24.04 nvidia-smi
Ako se ispis pojavi isti kao na domaćinu, sve radi. Ovo je test koji vredi zapamtiti — njime razdvajaš problem sa Dockerom od problema sa Ollamom.
Ollama u kontejneru
$ docker run -d \
--name ollama \
--gpus all \
-v ollama:/root/.ollama \
-p 127.0.0.1:11434:11434 \
--restart unless-stopped \
ollama/ollama
Tri stvari u ovoj komandi nose sav teret.
--gpus all propušta sve kartice. Za tačno određenu:
$ docker run --gpus '"device=0"' ... $ docker run --gpus '"device=GPU-a1b2..."' ...
-v ollama:/root/.ollama čuva modele van kontejnera. Bez ovoga svaki restart znači ponovno preuzimanje svega — a to je desetine gigabajta.
-p 127.0.0.1:11434:11434 vezuje port samo za lokalnu adresu. Zapis -p 11434:11434, koji ćeš viđati po uputstvima, otvara port prema celoj mreži i zaobilazi pravila firewalla, jer Docker piše sopstvena iptables pravila ispred tvojih. To je najčešći način da nezaštićen model završi na internetu.
$ docker logs -f ollama $ docker exec ollama ollama pull qwen3:8b $ docker exec -it ollama ollama run qwen3:8b
Provera koja je i ovde jedina bitna:
$ docker exec ollama ollama ps NAME ID SIZE PROCESSOR UNTIL qwen3:8b a1b2c3d4e5f6 6.2 GB 100% GPU 4 minutes from now
Ako piše bilo šta osim sto posto GPU, karticu kontejner ne koristi kako treba — vrati se na test sa nvidia-smi iz prethodnog odeljka.
Promenljive okruženja
Iste kao kod systemd jedinice, samo kroz -e:
$ docker run -d \
--name ollama \
--gpus all \
-v ollama:/root/.ollama \
-p 127.0.0.1:11434:11434 \
-e OLLAMA_KEEP_ALIVE=-1 \
-e OLLAMA_CONTEXT_LENGTH=16384 \
-e OLLAMA_KV_CACHE_TYPE=q8_0 \
-e OLLAMA_FLASH_ATTENTION=1 \
-e OLLAMA_NUM_PARALLEL=2 \
--restart unless-stopped \
ollama/ollama
Značenje svake stoji u tekstu o systemd jedinici. Vrednost OLLAMA_HOST unutar kontejnera ostavi na podrazumevanoj — izlaganje se rešava mapiranjem porta, ne promenljivom.
Gde su modeli
$ docker volume inspect ollama
[
{
"Mountpoint": "/var/lib/docker/volumes/ollama/_data",
"Name": "ollama"
}
]
$ sudo du -sh /var/lib/docker/volumes/ollama/_data
Ako je /var/lib/docker na maloj particiji, koristi direktorijum umesto imenovanog volumena:
$ sudo mkdir -p /data/ollama $ docker run -d --gpus all -v /data/ollama:/root/.ollama ...
Docker Compose
Za sve osim najkraćeg testa, compose je čitljiviji od duge komande:
$ nano compose.yaml
services:
ollama:
image: ollama/ollama
container_name: ollama
restart: unless-stopped
ports:
- "127.0.0.1:11434:11434"
volumes:
- /data/ollama:/root/.ollama
environment:
- OLLAMA_KEEP_ALIVE=-1
- OLLAMA_CONTEXT_LENGTH=16384
- OLLAMA_KV_CACHE_TYPE=q8_0
- OLLAMA_FLASH_ATTENTION=1
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
$ docker compose up -d $ docker compose logs -f $ docker compose exec ollama ollama pull qwen3:8b
Odeljak deploy.resources je compose ekvivalent za --gpus all. Zapis je nezgrapan, ali je to jedini ispravan način. Za određenu karticu zameni count: all sa device_ids: ['0'].
Više o samom alatu ima u tekstu o Docker Compose.
Ollama i Open WebUI zajedno
Ovde se prednost kontejnera prvi put stvarno vidi — dva servisa u istoj mreži, bez ijedne izmene na domaćinu:
services:
ollama:
image: ollama/ollama
container_name: ollama
restart: unless-stopped
volumes:
- /data/ollama:/root/.ollama
environment:
- OLLAMA_KEEP_ALIVE=-1
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
restart: unless-stopped
depends_on:
- ollama
ports:
- "127.0.0.1:3000:8080"
volumes:
- /data/open-webui:/app/backend/data
environment:
- OLLAMA_BASE_URL=http://ollama:11434
Ollama ovde uopšte nema mapiran port prema domaćinu. Dostupna je samo interno, po imenu servisa, a napolju stoji jedino veb interfejs. To je bolja postavka od one u kojoj su oba porta otvorena.
Sam interfejs je tema sledećeg teksta.
vLLM u kontejneru
Zvanična slika povlači sve zavisnosti, pa nema instalacije u virtuelno okruženje:
$ docker run -d \
--name vllm \
--gpus all \
--ipc=host \
-v /data/huggingface:/root/.cache/huggingface \
-p 127.0.0.1:8000:8000 \
--env HF_TOKEN \
vllm/vllm-openai:latest \
--model Qwen/Qwen3-8B-AWQ \
--served-model-name qwen3 \
--gpu-memory-utilization 0.90 \
--max-model-len 16384
Oznaka --ipc=host je obavezna. vLLM koristi deljenu memoriju između procesa, a podrazumevanih 64 MB u kontejneru mu nije dovoljno — bez nje servis puca pri učitavanju, sa greškom koja ni na šta ne upućuje. Alternativa je --shm-size=8g.
Zapis --env HF_TOKEN bez vrednosti prosleđuje promenljivu iz okruženja domaćina, pa token ne završava u istoriji ljuske ni u ispisu docker inspect.
Ostali parametri su isti kao u tekstu o vLLM-u.
Održavanje
$ docker pull ollama/ollama $ docker compose up -d
Compose sam prepoznaje noviju sliku i podiže kontejner ponovo. Modeli ostaju, jer su na volumenu.
Vraćanje na staru verziju, ako nova pravi problem:
$ docker run -d --gpus all ... ollama/ollama:0.11.4
Ovo je prednost koju systemd postavka nema — verziju vraćaš u sekundi, bez ponovne instalacije.
Čišćenje starih slika, koje se nagomilavaju brzo jer su velike:
$ docker image prune -a $ docker system df
Komanda docker system prune --volumes briše i volumene sa modelima. Nju izbegavaj.
Praktični scenariji
Scenario 1: kontejner ne vidi karticu
$ docker run --rm --gpus all ubuntu:24.04 nvidia-smi
Ako ni ovo ne radi, problem je u toolkit-u, ne u Ollami. Proveri da li je pokrenuta nvidia-ctk runtime configure i da li je Docker restartovan posle toga.
Scenario 2: posle restarta nema modela
Volumen nije bio podešen, pa je sve ostalo u sloju kontejnera koji je nestao. Dodaj -v i preuzmi ponovo.
Scenario 3: port je otvoren iako firewall to zabranjuje
Docker upisuje sopstvena pravila ispred tvojih. Rešenje je vezivanje za adresu pri mapiranju:
-p 127.0.0.1:11434:11434
Scenario 4: vLLM puca odmah po pokretanju u kontejneru
Nedostaje --ipc=host. Greška govori o deljenoj memoriji i ničemu drugom ne liči.
Scenario 5: nema mesta na disku, a modeli su obrisani
$ docker system df
Stare slike sa CUDA bibliotekama zauzimaju po nekoliko gigabajta svaka. Očisti ih sa docker image prune -a.
Scenario 6: dva kontejnera na istoj kartici, oba spora
Ne postoji podela memorije među kontejnerima — svaki uzima koliko stigne i oba se preliju. Na jednoj kartici drži jedan servis, ili im izričito dodeli različite kartice.
Kratka referenca
nvidia-container-toolkit— paket koji propušta karticunvidia-ctk runtime configure --runtime=docker— obavezan korak posle instalacijedocker run --rm --gpus all ubuntu:24.04 nvidia-smi— test propuštanja--gpus all— sve kartice--gpus '"device=0"'— određena kartica-v ollama:/root/.ollama— modeli preživljavaju restart-p 127.0.0.1:11434:11434— vezivanje za lokalnu adresu--ipc=host— obavezno za vLLM--env HF_TOKEN— prosleđivanje bez upisivanja vrednostideploy.resources.reservations.devices— GPU u compose fajludocker exec ollama ollama ps— provera da radi na karticidocker system df— zauzeće slikama i volumenima- Drajver ostaje na domaćinu, u kontejner ide samo CUDA
- Docker zaobilazi firewall — port uvek vezuj za adresu
Vežba
- Instaliraj toolkit i potvrdi da kontejner vidi karticu kroz test sa
nvidia-smi. - Pokreni Ollamu u kontejneru sa volumenom, preuzmi model, restartuj kontejner i potvrdi da je model ostao.
- Namerno izostavi
-v, uporedi šta se dešava posle restarta. - Napiši compose fajl sa Ollamom i Open WebUI, tako da Ollama nema mapiran port prema domaćinu.
- Proveri sa
ss -tulpnkoji su portovi stvarno otvoreni posle pokretanja compose postavke. - Uporedi brzinu istog modela u kontejneru i kroz systemd jedinicu na domaćinu.
Sledeći tekst u serijalu: Open WebUI — web interfejs za tvoje lokalne modele
Povezano:
- AI na Linux serveru — pregled celog serijala
- vLLM — produkciona inferencija — prethodni tekst
- Ollama kao systemd servis — jednostavnija alternativa bez kontejnera
- Instalacija Dockera na Linuxu — preduslov
- Docker Compose — više kontejnera odjednom
Comments
Post a Comment