Ollama in Docker Compose con GPU e archiviazione persistente dei modelli
Server Ollama con priorità alla configurazione, GPU e persistenza.
Ollama funziona egregiamente su hardware nativo. Diventa ancora più interessante quando lo si tratta come un servizio: un endpoint stabile, versioni bloccate, storage persistente e una GPU che o è disponibile o non lo è.
Questo post si concentra su un unico obiettivo: un “server” locale o mononodo riproducibile di Ollama utilizzando Docker Compose, con accelerazione GPU e storage persistente per i modelli.

Scrive intenzionalmente a fianco delle nozioni di base di Docker e Compose. Quando hai bisogno di un elenco compatto dei comandi che utilizzi più spesso (immagini, container, volumi, docker compose), la Scheda Rapida Docker è un buon compagno.
Quando vuoi HTTPS davanti a Ollama, un proxying corretto dello streaming e dei WebSocket, e controlli perimetrali (autenticazione, timeout, limiti di frequenza), consulta Ollama dietro un reverse proxy con Caddy o Nginx per HTTPS streaming.
Per capire come Ollama si integra con vLLM, Docker Model Runner, LocalAI e i compromessi dell’hosting cloud, consulta LLM Hosting nel 2026: Infrastruttura Locale, Self-Hosted e Cloud Confrontata.
Una volta che questa pila Compose gestisce traffico reale concorrente, la domanda successiva è spesso se Ollama sia ancora il motore giusto sotto di essa. Da Ollama a vLLM: Quando migrare il tuo server LLM locale fornisce un percorso di migrazione graduale che mantiene entrambi i container in esecuzione affiancati durante la convalida.
Quando Compose batte un’installazione su hardware nativo
Un’installazione nativa è senza attriti per un singolo sviluppatore su una singola macchina. Nel momento in cui hai una delle seguenti condizioni, Compose inizia a vincere in termini di ergonomia:
La configurazione di un team ne beneficia perché la definizione del servizio è un file che puoi revisionare, versionare e condividere. Un server mononodo ne beneficia perché gli aggiornamenti diventano un semplice aggiornamento del tag dell’immagine e un riavvio, mentre lo storage dei modelli rimane intatto (purché si trovi su un volume). Ollama tende anche a vivere accanto a sidecar: un’interfaccia Web, un reverse proxy, un gateway di autenticazione, un database vettoriale o un runtime di agenti. Compose è eccellente nel “avviare l’intera pila con un comando”, senza trasformare l’host in una variabile imprevedibile.
Questo approccio si allinea bene con il modo in cui è progettato il container ufficiale di Ollama: l’immagine esegue ollama serve in modo predefinito, espone la porta 11434 e è pensata per mantenere lo stato sotto una directory montabile. L’intero set di variabili d’ambiente OLLAMA_* lette da ollama serve — OLLAMA_HOST, OLLAMA_CONTEXT_LENGTH, OLLAMA_KEEP_ALIVE, OLLAMA_NUM_PARALLEL e il resto — è documentato nella Scheda Rapida CLI di Ollama.
Uno scheletro Compose che è effettivamente utile per Ollama
Inizia con due decisioni:
Primo, come bloccherai le versioni. L’immagine su Docker Hub è ollama/ollama, quindi puoi bloccare un tag specifico in .env invece di fare affidamento su latest.
Secondo, dove risiederanno i dati dei modelli. La documentazione ufficiale monta un volume su /root/.ollama in modo che i modelli non vengano ri-scaricati ogni volta che il container viene sostituito.
Ecco un file Compose che incorpora queste decisioni e mantiene le “manopole” vicine al servizio:
services:
ollama:
image: ollama/ollama:${OLLAMA_IMAGE_TAG:-latest}
container_name: ollama
restart: unless-stopped
# Mantienilo locale per impostazione predefinita, esponilo in seguito se necessario.
ports:
- "${OLLAMA_BIND_IP:-127.0.0.1}:11434:11434"
# Modelli persistenti e stato del server.
volumes:
- ollama:/root/.ollama
environment:
# L'immagine ufficiale ha già un predefinito 0.0.0.0:11434 all'interno del container,
# ma mantenerlo esplicito aiuta quando si fanno override in seguito.
- OLLAMA_HOST=0.0.0.0:11434
# Regolazioni del servizio.
- OLLAMA_KEEP_ALIVE=${OLLAMA_KEEP_ALIVE:-5m}
- OLLAMA_NUM_PARALLEL=${OLLAMA_NUM_PARALLEL:-1}
- OLLAMA_MAX_LOADED_MODELS=${OLLAMA_MAX_LOADED_MODELS:-1}
# Facoltativo, ma rilevante quando un'interfaccia basata su browser parla direttamente con Ollama.
# Vedere la sezione di Networking per il motivo per cui esiste.
- OLLAMA_ORIGINS=${OLLAMA_ORIGINS:-}
# La riserva GPU è una sezione separata sotto.
# Aggiungila solo su host che hanno effettivamente GPU NVIDIA.
volumes:
ollama: {}
Un corrispondente file .env rende noiosi gli aggiornamenti:
# Blocca la versione dell'immagine che hai testato.
OLLAMA_IMAGE_TAG=latest
# Locale per impostazione predefinita. Cambia in 0.0.0.0 quando esponi intenzionalmente il servizio.
OLLAMA_BIND_IP=127.0.0.1
# I tweaks di keep-alive bilanciano la latenza di avvio a freddo rispetto all'impronta di memoria.
OLLAMA_KEEP_ALIVE=5m
# Manopole di concorrenza.
OLLAMA_NUM_PARALLEL=1
OLLAMA_MAX_LOADED_MODELS=1
# Lascia vuoto a meno che tu non stia servendo client browser che colpiscono Ollama direttamente.
OLLAMA_ORIGINS=
Una sfumatura piccola ma importante: Ollama stesso ha un bind host predefinito di 127.0.0.1:11434 nella configurazione generale, ma l’immagine container ufficiale imposta OLLAMA_HOST=0.0.0.0:11434 in modo che il servizio sia raggiungibile tramite porte pubblicate.
Se vuoi un rapido controllo di sanità senza coinvolgere alcun SDK client, l’API di Ollama include un endpoint “elenca modelli locali” in GET /api/tags.
Storage persistente dei modelli e il modo meno doloroso per spostarlo
Se ti ricordi solo una cosa, che sia questa: il container deve avere uno storage persistente, altrimenti ogni rebuild è un nuovo download.
Ollama ti consente di scegliere la directory dei modelli utilizzando OLLAMA_MODELS. Nell’implementazione di riferimento, il predefinito è $HOME/.ollama/models, e l’impostazione di OLLAMA_MODELS lo sovrascrive.
All’interno dell’immagine Docker ufficiale, $HOME si mappa naturalmente al layout /root utilizzato dal mount del volume documentato (/root/.ollama), ed è esattamente per questo che gli esempi docker run ufficiali montano quella directory.
Ci sono due pattern di storage che tendono a funzionare bene nella pratica:
Un volume Docker nominato è il più semplice e portatile. È anche facile orfanizzarlo accidentalmente, quindi vale la pena nominarlo intenzionalmente (ad esempio ollama) e mantenerlo stabile attraverso i refactoring di Compose.
Un bind mount su un disco dedicato è migliore quando le dimensioni dei modelli iniziano a dominare il filesystem radice. In tal caso, o si monta l’intero /root/.ollama su quel disco, o si monta una directory personalizzata e si punta OLLAMA_MODELS verso di essa.
Se stai riorganizzando attivamente lo storage, è qui che una playbook esplicita per “spostare i modelli” aiuta. Vedi: move-ollama-models .
Supporto GPU NVIDIA con Compose e NVIDIA Container Toolkit
Ollama può utilizzare GPU NVIDIA in Docker, ma l’immagine non può fare apparire una GPU dal nulla. L’host ha bisogno di driver NVIDIA funzionanti e del NVIDIA Container Toolkit, e Docker deve essere configurato per utilizzarlo. La documentazione Docker di Ollama chiama esplicitamente in causa l’installazione di nvidia-container-toolkit, la configurazione del runtime tramite nvidia-ctk runtime configure --runtime=docker e il riavvio di Docker.
Sul lato Compose, il modo pulito e moderno è la riserva di dispositivi. Docker documenta l’accesso alle GPU in Compose utilizzando deploy.resources.reservations.devices, con capabilities: [gpu], driver: nvidia, e count (incluso all) oppure device_ids.
Aggiungi questo al servizio ollama quando sei su un host NVIDIA:
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
Se hai più GPU e vuoi mantenere Ollama su dispositivi specifici, passa da count a device_ids come documentato da Docker (sono mutualmente esclusivi).
A volte vedrai esempi Compose legacy che usano runtime: nvidia. Questo può fallire su configurazioni più recenti con errori come “unknown or invalid runtime name: nvidia”, che è un forte indizio che dovresti passare al pattern di riserva dei dispositivi supportato e assicurarti che il toolkit sia configurato sull’host.
Un dettaglio utile che sta in bella vista: l’immagine ufficiale ollama/ollama imposta NVIDIA_VISIBLE_DEVICES=all e NVIDIA_DRIVER_CAPABILITIES=compute,utility. Queste sono manopole standard riconosciute dal runtime container NVIDIA e sono già presenti a meno che tu non le sovrascriva.
Per confermare se stai effettivamente ottenendo inferenza GPU (non solo un container che parte), Ollama raccomanda di usare ollama ps e controllare la colonna “Processor”, che mostra se il modello è in memoria GPU.
Controllo di realtà della piattaforma: Ollama nota che l’accelerazione GPU in Docker è disponibile su Linux (e Windows con WSL2), e non disponibile su Docker Desktop per macOS a causa della mancanza di passthrough GPU.
Scelte di Networking: host vs bridge, porte e CORS
Il Networking è dove nascono la maggior parte dei bug “si avvia ma la mia app non riesce a connettersi”.
Networking Bridge con porte pubblicate
La rete Compose predefinita è una rete bridge. In questa configurazione, pubblicare 11434:11434 rende Ollama raggiungibile dall’host sulla porta 11434, mentre gli altri container dovrebbero parlarci utilizzando il nome del servizio ollama (non localhost). Molte persone si imbambolano su questo perché localhost all’interno di un container significa “questo container”, non “il container Ollama”.
Ollama stesso esegue un server HTTP sulla porta 11434 (l’immagine lo espone), e la convenzione comune è che i client usino http://localhost:11434 sull’host quando le porte sono pubblicate.
Networking Host
network_mode: host può essere allettante su un server mononodo perché rimuove la pubblicazione delle porte e semplifica la semantica di localhost. Il compromesso è che perdi i benefici di isolamento e namespacing di una rete bridge, e sei più probabile che tu incontri conflitti di porte.
Esporre Ollama intenzionalmente
Ollama su un’installazione normale si lega a 127.0.0.1 per impostazione predefinita, e il modo documentato per cambiare l’indirizzo di binding è OLLAMA_HOST.
In Docker, hai due livelli:
Indirizzo di binding di Ollama, controllato da OLLAMA_HOST (l’immagine container predefinita si lega su tutte le interfacce all’interno del container).
Raggiungibilità dall’esterno del container, controllata da ports di Compose e dal firewall dell’host.
Un pattern che mi piace è “legare localmente per impostazione predefinita” tramite 127.0.0.1:11434:11434, per poi passare a 0.0.0.0:11434:11434 solo quando ho un motivo per esporlo.
Client browser e OLLAMA_ORIGINS
Se un’interfaccia basata su browser o un’estensione chiama Ollama direttamente, sei nel territorio CORS. Ollama consente richieste cross-origin da 127.0.0.1 e 0.0.0.0 per impostazione predefinita, e puoi configurare origini aggiuntive utilizzando OLLAMA_ORIGINS.
Questo è importante anche su un singolo nodo, perché “funziona con curl” non significa “funziona da un’app browser”.
Pattern di upgrade e rollback adatti a un server mononodo
Ollama evolve rapidamente. Il tuo file Compose può rendere quel processo calmo invece di una sorpresa notturna.
Upgrade aumentando un tag, non sperando che “latest” si comporti
La strategia di upgrade più pratica è bloccare l’immagine a un tag noto e buono in .env e aumentarlo intenzionalmente. L’immagine è pubblicata come ollama/ollama su Docker Hub.
Poiché i dati dei modelli e lo stato del server sono memorizzati sotto una directory montata (/root/.ollama nella documentazione ufficiale), sostituire il container non implica ri-scaricare i modelli.
Il rollback è solo il cambio del tag indietro
Il rollback è lo stesso meccanismo al contrario: imposta il tag precedente, ricrea il container, mantieni lo stesso volume. È qui che il bloccaggio si ripaga.
La migrazione dei dati è principalmente sui percorsi di storage
La maggior parte delle “migrazioni” in un setup mononodo non riguardano gli schemi del database. Riguardano il layout del disco. Se cambi la directory dei modelli (tramite OLLAMA_MODELS) o sposti il volume montato su un nuovo disco, stai facendo una migrazione dei dati che tu lo chiami così o no.
Se vuoi una guida pratica per riorganizzare la directory dei modelli su macchine reali, consulta: move-ollama-models .
Un’ultima nota facile da perdere: la documentazione API di Ollama afferma esplicitamente che l’API è prevista per essere stabile e compatibile all’indietro, con rare deprecazioni annunciate nelle note di rilascio. Questo rende “aggiornare il server, mantenere i client funzionanti” un’aspettativa ragionevole predefinita per un endpoint di servizio mononodo.
Fallimenti comuni: permessi GPU, disaccordo driver e OOM
Questa sezione è deliberatamente guidata dai sintomi. L’obiettivo non è “ogni possibile errore Docker”, solo i fallimenti che compaiono specificamente nei setup Ollama + GPU + storage persistente.
GPU visibile sull’host, mancante nel container
Se l’host ha un driver NVIDIA funzionante ma il container non vede una GPU, le cause comuni sono:
Il NVIDIA Container Toolkit non è installato o il runtime Docker non è configurato tramite nvidia-ctk. La documentazione Docker di Ollama lo chiama direttamente.
Compose non sta riservando un dispositivo GPU. Il modo supportato è deploy.resources.reservations.devices con la capacità gpu come documentato da Docker.
Una configurazione legacy runtime: nvidia viene usata su un daemon che non la riconosce, producendo “unknown or invalid runtime name: nvidia”.
Per la convalida, ollama ps ti fornisce un controllo pragmatico: mostra se un modello è caricato in memoria GPU.
Permesso negato sui dispositivi GPU
Il sapore “permesso negato” dei fallimenti GPU punta tipicamente a vincoli di ambiente piuttosto che a Ollama stesso. Esempi includono l’esecuzione di Docker rootless, policy di sicurezza, o nodi di dispositivo non esposti come previsto. La documentazione di supporto GPU per Docker Compose è esplicita che l’host deve avere dispositivi GPU e che il daemon Docker deve essere impostato di conseguenza.
In caso di dubbio, riduci le variabili: conferma la configurazione del toolkit (host), poi conferma la riserva GPU (Compose), poi conferma l’utilizzo GPU (ollama ps).
Driver sbagliato, aspettativa sbagliata
Ollama in Docker si affida allo stack di driver dell’host. Se il driver dell’host è mancante, troppo vecchio o configurato male, vedrai fallimenti che sembrano “Ollama è rotto” ma sono in realtà “lo stack CUDA non è utilizzabile”. La documentazione ufficiale colloca il toolkit container e la configurazione del daemon Docker come prerequisiti per l’uso di GPU NVIDIA.
Out of memory: VRAM o RAM scompare velocemente
L’OOM è il modo di fallimento più prevedibile per l’inferenza locale, e di solito è auto-inflitto dalla configurazione.
Ollama supporta l’elaborazione concorrente tramite più modelli caricati e la gestione parallela delle richieste, ma è vincolato dalla memoria disponibile (RAM di sistema per inferenza CPU, VRAM per inferenza GPU). Quando viene usata l’inferenza GPU, i nuovi modelli devono entrare in VRAM per consentire carichi di modelli concorrenti.
Due dettagli di configurazione vale la pena trattare come “impostazioni di server” di prima classe:
OLLAMA_NUM_PARALLEL aumenta l’elaborazione parallela delle richieste per modello, ma la memoria richiesta scala con OLLAMA_NUM_PARALLEL * OLLAMA_CONTEXT_LENGTH.
OLLAMA_KEEP_ALIVE controlla per quanto tempo i modelli rimangono caricati (predefinito è 5 minuti). Mantenere i modelli caricati riduce la latenza di avvio a freddo, ma fissa anche la memoria.
Se stai stabilizzando un servizio mononodo sotto carico, le correzioni non drammatiche di solito sembrano:
Ridurre la concorrenza e i predefiniti di contesto prima di cambiare qualsiasi altra cosa.
Limitare quanti modelli sono consentiti di rimanere caricati contemporaneamente.
Considerare funzionalità di riduzione della memoria come Flash Attention (OLLAMA_FLASH_ATTENTION=1) e tipi di cache K/V a precisione inferiore (OLLAMA_KV_CACHE_TYPE) quando il collo di bottiglia è la memoria, non la potenza di calcolo grezza.
Quando non è Ollama: scegliere Docker Model Runner invece
A volte il “fallimento” è in realtà un disaccordo di tooling. Se la tua organizzazione ha già standardizzato su artefatti e workflow nativi Docker, Docker Model Runner (DMR) può essere un’opzione migliore rispetto all’esecuzione di Ollama come container di servizio a lungo termine.
Docker posiziona DMR come un modo per gestire, eseguire e servire modelli direttamente tramite Docker, scaricando da Docker Hub o da altri registri OCI, e servendo API compatibili con OpenAI e Ollama.
Supporta anche più motori di inferenza (incluso llama.cpp, e vLLM su Linux con GPU NVIDIA), il che può contare se ti importa delle caratteristiche di throughput, non solo di “eseguire un modello localmente”.
Se vuoi un riferimento comandi pratico e un angolo di confronto più approfondito, consulta: Docker Model Runner Cheatsheet: Comandi & Esempi.