Ollama dans Docker Compose avec GPU et stockage persistant des modèles

Serveur Ollama orienté composition, avec GPU et persistance.

Sommaire

Ollama fonctionne parfaitement sur du matériel nu. Cela devient encore plus intéressant lorsque vous le traitez comme un service : une extrémité stable, des versions figées, un stockage persistant et une GPU qui est soit disponible, soit non.

Cet article se concentre sur un seul objectif : un serveur Ollama local ou mono-nœud reproductible utilisant Docker Compose, avec accélération GPU et stockage de modèles persistant.

ollama docker compose

Il saute intentionnellement les bases génériques de Docker et Compose. Lorsque vous avez besoin d’une liste compacte des commandes que vous utilisez le plus souvent (images, conteneurs, volumes, docker compose), le Cheat Sheet Docker est un bon compagnon.

Si vous souhaitez HTTPS devant Ollama, un proxy de streaming et WebSocket correct, et des contrôles de bord (authentification, délais d’attente, limites de débit), consultez Ollama derrière un proxy inversé avec Caddy ou Nginx pour le streaming HTTPS.

Pour comprendre comment Ollama s’intègre aux côtés de vLLM, Docker Model Runner, LocalAI et les compromis d’hébergement cloud, consultez Hébergement LLM en 2026 : Infrastructure locale, auto-hébergée et cloud comparée.

Quand Compose bat une installation sur matériel nu

Une installation native est sans friction pour un développeur sur une seule machine. Dès que vous avez l’un des éléments suivants, Compose commence à gagner en ergonomie :

Une configuration d’équipe en bénéficie car la définition du service est un fichier que vous pouvez examiner, versionner et partager. Un serveur mono-nœud en bénéficie car les mises à jour se résument à changer le tag de l’image et redémarrer, tandis que votre stockage de modèles reste en place (tant qu’il est sur un volume). Ollama a également tendance à vivre à côté de sidecars : une interface web, un proxy inversé, une passerelle d’authentification, une base de données vectorielle ou un runtime d’agent. Compose est bon pour “une commande pour démarrer toute la pile”, sans transformer votre hôte en flocon de neige.

Cette approche s’aligne bien avec la façon dont le conteneur officiel Ollama est conçu : l’image exécute ollama serve par défaut, expose le port 11434 et est conçue pour conserver l’état sous un répertoire montable.

Un squelette Compose réellement utile pour Ollama

Commencez par deux décisions :

Premièrement, comment vous allez figer les versions. L’image Docker Hub est ollama/ollama, vous pouvez donc figer un tag spécifique dans .env au lieu de vous fier à latest.

Deuxièmement, où les données du modèle vivront. La documentation officielle monte un volume sur /root/.ollama afin que les modèles ne soient pas rétéléchargés à chaque remplacement du conteneur.

Voici un fichier Compose qui intègre ces décisions et garde les “molettes” proches du service :

services:
  ollama:
    image: ollama/ollama:${OLLAMA_IMAGE_TAG:-latest}
    container_name: ollama
    restart: unless-stopped

    # Gardez-le local par défaut, exposez-le plus tard si nécessaire.
    ports:
      - "${OLLAMA_BIND_IP:-127.0.0.1}:11434:11434"

    # Modèles persistants et état du serveur.
    volumes:
      - ollama:/root/.ollama

    environment:
      # L'image officielle est déjà par défaut sur 0.0.0.0:11434 à l'intérieur du conteneur,
      # mais le garder explicite aide lorsque vous modifiez des éléments plus tard.
      - OLLAMA_HOST=0.0.0.0:11434

      # Réglages du service.
      - OLLAMA_KEEP_ALIVE=${OLLAMA_KEEP_ALIVE:-5m}
      - OLLAMA_NUM_PARALLEL=${OLLAMA_NUM_PARALLEL:-1}
      - OLLAMA_MAX_LOADED_MODELS=${OLLAMA_MAX_LOADED_MODELS:-1}

      # Optionnel, mais pertinent lorsqu'une interface UI basée sur le navigateur communique directement avec Ollama.
      # Consultez la section Réseau pour comprendre pourquoi cela existe.
      - OLLAMA_ORIGINS=${OLLAMA_ORIGINS:-}

    # La réservation GPU est une section séparée ci-dessous.
    # Ajoutez-la uniquement sur les hôtes qui ont réellement des GPU NVIDIA.

volumes:
  ollama: {}

Un .env correspondant garde les mises à jour ennuyeuses :

# Figez la version de l'image que vous avez testée.
OLLAMA_IMAGE_TAG=latest

# Local par défaut. Changez en 0.0.0.0 lorsque vous l'exposez intentionnellement.
OLLAMA_BIND_IP=127.0.0.1

# Réglages Keep-alive pour la latence de démarrage à froid vs empreinte mémoire.
OLLAMA_KEEP_ALIVE=5m

# Molettes de concurrence.
OLLAMA_NUM_PARALLEL=1
OLLAMA_MAX_LOADED_MODELS=1

# Laissez vide sauf si vous servez des clients navigateur qui touchent Ollama directement.
OLLAMA_ORIGINS=

Une petite nuance importante : Ollama lui-même a une liaison d’hôte par défaut de 127.0.0.1:11434 dans la configuration générale, mais l’image de conteneur officielle définit OLLAMA_HOST=0.0.0.0:11434 afin que le service soit accessible via les ports publiés.

Si vous voulez une vérification de cohérence rapide sans impliquer de SDK client, l’API Ollama inclut une extrémité “list local models” à GET /api/tags.

Stockage persistant des modèles et la façon la moins douloureuse de les déplacer

Si vous n’en retenez qu’une chose, que ce soit celle-ci : le conteneur doit avoir un stockage persistant, sinon chaque reconstruction est un rétéléchargement.

Ollama vous permet de choisir le répertoire des modèles en utilisant OLLAMA_MODELS. Dans l’implémentation de référence, la valeur par défaut est $HOME/.ollama/models, et définir OLLAMA_MODELS remplace cela.

À l’intérieur de l’image Docker officielle, $HOME se mappe naturellement sur la disposition /root utilisée par le montage de volume documenté (/root/.ollama), ce qui explique exactement pourquoi les exemples officiels docker run montent ce répertoire.

Il existe deux modèles de stockage qui fonctionnent bien en pratique :

Un volume Docker nommé est le plus simple et portable. Il est également facile d’être orphelin par accident, il vaut donc mieux le nommer intentionnellement (par exemple ollama) et le garder stable à travers les refactorisations Compose.

Un montage de liaison vers un disque dédié est meilleur lorsque la taille des modèles commence à dominer votre système de fichiers racine. Dans ce cas, vous montez soit tout /root/.ollama sur ce disque, soit vous montez un répertoire personnalisé et pointez OLLAMA_MODELS vers lui.

Si vous réorganisez activement le stockage, c’est là qu’un playbook explicite “move models” aide. Voir : move-ollama-models .

Prise en charge NVIDIA GPU avec Compose et le NVIDIA Container Toolkit

Ollama peut utiliser les GPU NVIDIA dans Docker, mais l’image ne peut pas faire apparaître un GPU par magie. L’hôte a besoin de pilotes NVIDIA fonctionnels et du NVIDIA Container Toolkit, et Docker doit être configuré pour l’utiliser. La documentation Docker d’Ollama appelle explicitement à installer nvidia-container-toolkit, configurer le runtime via nvidia-ctk runtime configure --runtime=docker, et redémarrer Docker.

Côté Compose, la méthode propre et moderne est la réservation de dispositifs. Docker documente l’accès GPU dans Compose en utilisant deploy.resources.reservations.devices, avec capabilities: [gpu], driver: nvidia, et soit count (incluant all) soit device_ids.

Ajoutez ceci au service ollama lorsque vous êtes sur un hôte NVIDIA :

deploy:
  resources:
    reservations:
      devices:
        - driver: nvidia
          count: all
          capabilities: [gpu]

Si vous avez plusieurs GPU et que vous souhaitez garder Ollama sur des dispositifs spécifiques, passez de count à device_ids comme documenté par Docker (ils sont mutuellement exclusifs).

Vous verrez parfois des exemples Compose legacy utilisant runtime: nvidia. Cela peut échouer sur les configurations plus récentes avec des erreurs comme “unknown or invalid runtime name: nvidia”, ce qui est un indice fort indiquant que vous devriez passer au modèle de réservation de dispositif supporté et vous assurer que le toolkit est configuré sur l’hôte.

Un détail utile caché en vue : l’image officielle ollama/ollama définit NVIDIA_VISIBLE_DEVICES=all et NVIDIA_DRIVER_CAPABILITIES=compute,utility. Ce sont des molettes standard reconnues par le runtime de conteneur NVIDIA, et elles sont déjà présentes sauf si vous les écrasez.

Pour confirmer si vous obtenez réellement une inférence GPU (pas juste un conteneur qui démarre), Ollama recommande d’utiliser ollama ps et de vérifier la colonne “Processor”, qui indique si le modèle est en mémoire GPU.

Vérification de réalité de la plateforme : Ollama note que l’accélération GPU dans Docker est disponible sur Linux (et Windows avec WSL2), et non disponible sur Docker Desktop pour macOS en raison de l’absence de transpas GPU.

Choix de réseau : hôte vs pont, ports et CORS

Le réseau est là où la plupart des bugs “ça marche mais mon app ne peut pas se connecter” proviennent.

Réseau de pont avec ports publiés

Le réseau Compose par défaut est un réseau de pont. Dans cette configuration, publier 11434:11434 rend Ollama accessible depuis l’hôte sur le port 11434, tandis que les autres conteneurs devraient lui parler en utilisant le nom de service ollama (pas localhost). Beaucoup de gens trébuchent là-dessus car localhost à l’intérieur d’un conteneur signifie “ce conteneur”, pas “le conteneur Ollama”.

Ollama lui-même exécute un serveur HTTP sur le port 11434 (l’image l’expose), et la convention commune est que les clients utilisent http://localhost:11434 sur l’hôte lorsque les ports sont publiés.

Réseau hôte

network_mode: host peut être tentant sur un serveur mono-nœud car il supprime la publication de port et rend les sémantiques de localhost plus simples. Le compromis est que vous perdez les avantages d’isolement et d’espacement de nommage d’un réseau de pont, et vous êtes plus susceptible de rencontrer des conflits de ports.

Exposer Ollama intentionnellement

Ollama sur une installation normale se lie par défaut à 127.0.0.1, et la façon documentée de changer l’adresse de liaison est OLLAMA_HOST.

Dans Docker, vous avez deux couches :

Adresse de liaison Ollama, contrôlée par OLLAMA_HOST (l’image de conteneur se lie par défaut sur toutes les interfaces à l’intérieur du conteneur).

Accessibilité depuis l’extérieur du conteneur, contrôlée par ports Compose et le pare-feu de l’hôte.

Un modèle que j’aime est “lier localement par défaut” via 127.0.0.1:11434:11434, puis passer à 0.0.0.0:11434:11434 uniquement lorsque j’ai une raison de l’exposer.

Clients navigateur et OLLAMA_ORIGINS

Si une interface UI basée sur un navigateur ou une extension appelle Ollama directement, vous êtes dans le territoire CORS. Ollama autorise les requêtes inter-domaines depuis 127.0.0.1 et 0.0.0.0 par défaut, et vous pouvez configurer des origines supplémentaires en utilisant OLLAMA_ORIGINS.

Cela compte même sur un nœud unique, car “ça marche avec curl” ne signifie pas “ça marche depuis une app navigateur”.

Modèles de mise à niveau et de rollback adaptés à un serveur mono-nœud

Ollama évolue rapidement. Votre fichier Compose peut rendre cela un processus calme plutôt qu’une surprise tardive.

Mise à niveau en changeant un tag, pas en espérant que “latest” se comporte bien

La stratégie de mise à niveau la plus pratique est de figer l’image sur un tag connu comme bon dans .env, et de le faire monter intentionnellement. L’image est publiée sous ollama/ollama sur Docker Hub.

Parce que les données de modèle et l’état du serveur sont stockées sous un répertoire monté (/root/.ollama dans la documentation officielle), remplacer le conteneur n’implique pas de rétéléchargement des modèles.

Le rollback n’est que de changer le tag en arrière

Le rollback est le même mécanisme en sens inverse : définir le tag précédent, recréer le conteneur, garder le même volume. C’est là que le fige paie pour lui-même.

La migration de données concerne principalement les chemins de stockage

La plupart des “migrations” dans une configuration mono-nœud ne concernent pas les schémas de base de données. Elles concernent la disposition du disque. Si vous changez le répertoire des modèles (via OLLAMA_MODELS) ou déplacez le volume monté vers un nouveau disque, vous effectuez une migration de données, que vous l’appeliez ainsi ou non.

Si vous voulez un guide pratique pour réorganiser le répertoire de modèle sur de vraies machines, consultez : move-ollama-models .

Une note finale facile à manquer : la documentation API d’Ollama dit explicitement que l’API est censée être stable et rétrocompatible, avec des dépréciations rares annoncées dans les notes de version. Cela rend “mettre à jour le serveur, garder les clients fonctionnels” une attente par défaut raisonnable pour une extrémité de service mono-nœud.

Échecs courants : permissions GPU, incohérence de pilote et OOM

Cette section est délibérément basée sur les symptômes. L’objectif n’est pas “toute erreur Docker possible”, mais uniquement les échecs qui apparaissent spécifiquement dans les configurations Ollama + GPU + stockage persistant.

GPU visible sur l’hôte, manquant dans le conteneur

Si l’hôte a un pilote NVIDIA fonctionnel mais que le conteneur ne voit pas de GPU, les causes courantes sont :

Le NVIDIA Container Toolkit n’est pas installé ou le runtime Docker n’est pas configuré via nvidia-ctk. La documentation Docker d’Ollama le signale directement.

Compose ne réserve pas de dispositif GPU. La méthode supportée est deploy.resources.reservations.devices avec la capacité gpu comme documenté par Docker.

Une configuration legacy runtime: nvidia est utilisée sur un démon qui ne le reconnaît pas, produisant “unknown or invalid runtime name: nvidia”.

Pour la validation, ollama ps vous donne une vérification pragmatique : il montre si un modèle est chargé en mémoire GPU.

Permission refusée sur les dispositifs GPU

La saveur “permission denied” des échecs GPU pointe généralement vers des contraintes environnementales plutôt que vers Ollama lui-même. Les exemples incluent l’exécution de Docker sans racine, des politiques de sécurité, ou des nœuds de dispositifs qui ne sont pas exposés comme prévu. La documentation de support GPU Docker Compose est explicite : l’hôte doit avoir des dispositifs GPU et le démon Docker doit être configuré en conséquence.

En cas de doute, réduisez les variables : confirmez la configuration du toolkit (hôte), puis confirmez la réservation GPU (Compose), puis confirmez l’utilisation GPU (ollama ps).

Mauvais pilote, mauvaise attente

Ollama dans Docker dépend de la pile de pilote de l’hôte. Si le pilote de l’hôte est manquant, trop ancien ou mal configuré, vous verrez des échecs qui ressemblent à “Ollama est cassé” mais qui sont vraiment “la pile CUDA n’est pas utilisable”. La documentation officielle place le toolkit de conteneur et la configuration du démon Docker comme prérequis pour l’utilisation de GPU NVIDIA.

Mémoire insuffisante : la VRAM ou la RAM disparaît rapidement

OOM est le mode d’échec le plus prévisible pour l’inférence locale, et il est généralement auto-infligé par la configuration.

Ollama prend en charge le traitement concurrent via plusieurs modèles chargés et la gestion de requêtes parallèles, mais il est contraint par la mémoire disponible (RAM système pour l’inférence CPU, VRAM pour l’inférence GPU). Lorsque l’inférence GPU est utilisée, les nouveaux modèles doivent tenir dans la VRAM pour permettre des chargements de modèles concurrents.

Deux détails de configuration valent la peine d’être traités comme des “paramètres serveur” de première classe :

OLLAMA_NUM_PARALLEL augmente le traitement de requêtes parallèles par modèle, mais la mémoire requise évolue avec OLLAMA_NUM_PARALLEL * OLLAMA_CONTEXT_LENGTH.

OLLAMA_KEEP_ALIVE contrôle combien de temps les modèles restent chargés (par défaut 5 minutes). Garder les modèles chargés réduit la latence de démarrage à froid, mais cela fixe également la mémoire.

Si vous stabilisez un service mono-nœud sous charge, les corrections non dramatiques ressemblent généralement à :

Réduire la parallélisation et les paramètres de contexte par défaut avant de changer quoi que ce soit d’autre.

Limiter le nombre de modèles autorisés à rester chargés en même temps.

Envisager des fonctionnalités de réduction de mémoire comme Flash Attention (OLLAMA_FLASH_ATTENTION=1) et des types de cache K/V à précision inférieure (OLLAMA_KV_CACHE_TYPE) lorsque votre goulot d’étranglement est la mémoire, pas le calcul brut.

Quand ce n’est pas Ollama : choisir Docker Model Runner à la place

Parfois, l’“échec” est vraiment un problème d’outillage. Si votre organisation standardise déjà sur des artefacts et workflows natifs Docker, Docker Model Runner (DMR) peut être un meilleur choix que d’exécuter Ollama comme un conteneur de service à longue durée de vie.

Docker positionne DMR comme un moyen de gérer, exécuter et servir des modèles directement via Docker, en tirant de Docker Hub ou d’autres registres OCI, et en servant des API compatibles OpenAI et Ollama.

Il prend également en charge plusieurs moteurs d’inférence (y compris llama.cpp, et vLLM sur Linux avec GPU NVIDIA), ce qui peut compter si vous vous souciez des caractéristiques de débit, pas juste “exécuter un modèle localement”.

Si vous voulez une référence de commande pratique et un angle de comparaison plus profond, consultez : Docker Model Runner Cheatsheet: Commands & Examples.