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

Serveur Ollama axé sur la composition, avec GPU et persistance.

Sommaire

Ollama fonctionne très bien sur du matériel nu. Cela devient encore plus intéressant lorsque vous la traitez comme un service : un point de terminaison stable, des versions épinglées, un stockage persistant et une carte graphique (GPU) qui est soit disponible, soit ne l’est pas.

Cet article se concentre sur un objectif précis : un « serveur » local ou mononœud Ollama reproductible à l’aide de Docker Compose, avec accélération GPU et stockage persistant des modèles.

ollama docker compose

Il évite intentionnellement les bases génériques de Docker et de Compose. Lorsque vous avez besoin d’une liste compacte des commandes les plus utilisées (images, conteneurs, volumes, docker compose), l’Aide-mémoire Docker est un bon compagnon.

Lorsque vous souhaitez le HTTPS devant Ollama, un acheminement (proxying) correct du flux en continu (streaming) et des WebSockets, ainsi que des contrôles de bord (authentification, délais d’attente, limites de débit), consultez Ollama derrière un proxy inverse avec Caddy ou Nginx pour le streaming HTTPS.

Pour savoir comment Ollama s’insère aux côtés de vLLM, Docker Model Runner, LocalAI et les compromis d’hébergement cloud, consultez Hébergement de LLM en 2026 : Comparaison des infrastructures locales, auto-hébergées et cloud.

Une fois que cette pile Compose gère un trafic concurrentiel réel, la question suivante est souvent de savoir si Ollama est toujours le bon moteur sous-jacent. D’Ollama à vLLM : Quand migrer votre serveur de LLM local fournit un chemin de migration progressif qui permet de maintenir les deux conteneurs actifs côte à côte pendant la validation.

Quand Compose surpasse une installation sur matériel nu

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

Une configuration d’équipe en profite car la définition du service est un fichier que vous pouvez relire, versionner et partager. Un serveur mononœud en profite car les mises à niveau deviennent une simple mise à jour d’étiquette d’image (tag) et un redémarrage, tandis que votre stockage de modèles reste en place (tant qu’il est sur un volume). Ollama a également tendance à vivre aux côtés de co-services (sidecars) : une interface Web, un proxy inverse, une passerelle d’authentification, une base de données vectorielle ou un environnement d’exécution d’agent. Compose est bon pour « une commande pour démarrer toute la pile », sans transformer votre hôte en une configuration unique et difficile à reproduire (snowflake).

Cette approche s’aligne bien sur la façon dont l’image conteneur officielle d’Ollama est conçue : l’image exécute ollama serve par défaut, expose le port 11434 et est destinée à conserver l’état sous un dossier montable. L’ensemble des variables d’environnement OLLAMA_* que ollama serve lit — OLLAMA_HOST, OLLAMA_CONTEXT_LENGTH, OLLAMA_KEEP_ALIVE, OLLAMA_NUM_PARALLEL et les autres — est documenté dans l’Aide-mémoire CLI Ollama.

Un squelette Compose réellement utile pour Ollama

Commencez par deux décisions :

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

Deuxièmement, où les données des modèles résideront. La documentation officielle monte un volume vers /root/.ollama afin que les modèles ne soient pas re-téléchargés chaque fois que le conteneur est remplacé.

Voici un fichier Compose qui intègre ces décisions et garde les « réglages » proches du service :

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

    # Le garder local par défaut, l'exposer 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 définit déjà 0.0.0.0:11434 par défaut à l'intérieur du conteneur,
      # mais le garder explicite aide lorsque vous passez outre les paramètres 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}

      # Facultatif, mais pertinent lorsqu'une interface utilisateur basée sur le navigateur parle directement à Ollama.
      # Consultez la section Réseau pour savoir pourquoi cela existe.
      - OLLAMA_ORIGINS=${OLLAMA_ORIGINS:-}

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

volumes:
  ollama: {}

Un fichier .env correspondant rend les mises à niveau monotones :

# Épinglez 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

# Le réglage de la persistance ajuste la latence de démarrage à froid par rapport à l'empreinte mémoire.
OLLAMA_KEEP_ALIVE=5m

# Réglages de la concurrence.
OLLAMA_NUM_PARALLEL=1
OLLAMA_MAX_LOADED_MODELS=1

# Laissez vide sauf si vous servez des clients navigateur qui accèdent directement à Ollama.
OLLAMA_ORIGINS=

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

Si vous souhaitez une vérification rapide de bon sens sans impliquer de SDK de client, l’API Ollama inclut un point de terminaison « lister les modèles locaux » à GET /api/tags.

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

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

Ollama vous permet de choisir le répertoire des modèles à l’aide de OLLAMA_MODELS. Dans l’implémentation de référence, la valeur par défaut est $HOME/.ollama/models, et la définition de OLLAMA_MODELS l’écrase.

À l’intérieur de l’image Docker officielle, $HOME correspond naturellement à la structure /root utilisée par le montage de volume documenté (/root/.ollama), ce qui explique exactement pourquoi les exemples docker run officiels 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. C’est aussi facile d’oublier de l’orpheliner, donc il vaut la peine de le nommer intentionnellement (par exemple ollama) et de le garder stable entre les refactorisations Compose.

Un montage lié (bind mount) vers un disque dédié est meilleur lorsque les tailles des modèles commencent à dominer votre système de fichiers racine. Dans ce cas, vous montez soit tout /root/.ollama vers ce disque, soit vous montez un répertoire personnalisé et pointez OLLAMA_MODELS vers celui-ci.

Si vous réorganisez activement le stockage, c’est ici qu’un plan de jeu « déplacer les modèles » explicite aide. Voir : move-ollama-models .

Prise en charge des GPU NVIDIA 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 cite explicitement l’installation de nvidia-container-toolkit, la configuration du runtime via nvidia-ctk runtime configure --runtime=docker, et le redémarrage de Docker.

Côté Compose, la méthode propre et moderne est la réservation de périphériques. Docker documente l’accès GPU dans Compose en utilisant deploy.resources.reservations.devices, avec capabilities: [gpu], driver: nvidia, et soit count (y compris 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 périphériques spécifiques, passez de count à device_ids comme documenté par Docker (ils sont mutuellement exclusifs).

Vous verrez parfois des exemples Compose hérités qui utilisent runtime: nvidia. Cela peut échouer sur les nouvelles configurations avec des erreurs comme « unknown or invalid runtime name: nvidia », ce qui est un fort indice que vous devriez passer au modèle de réservation de périphérique pris en charge et vous assurer que le toolkit est configuré sur l’hôte.

Un détail utile qui se cache en pleine lumière : l’image officielle ollama/ollama définit NVIDIA_VISIBLE_DEVICES=all et NVIDIA_DRIVER_CAPABILITIES=compute,utility. Ce sont des réglages standards reconnus par le runtime conteneur NVIDIA, et ils sont déjà présents à moins que vous ne les écrasiez.

Pour confirmer si vous obtenez réellement une inférence GPU (et pas juste un conteneur qui démarre), Ollama recommande d’utiliser ollama ps et de vérifier la colonne « Processor », qui montre si le modèle est sur la 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 du manque de transmission directe (passthrough) GPU.

Choix de réseau : hôte par rapport au pont, ports et CORS

Le réseau est l’endroit où se trouvent la plupart des bogues « ça tourne mais mon application ne peut pas se connecter ».

Réseau en pont (bridge) avec ports publiés

Le réseau Compose par défaut est un réseau en pont. Dans cette configuration, la publication de 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 du service ollama (et non localhost). Beaucoup de gens trébuchent sur cela parce que localhost à l’intérieur d’un conteneur signifie « ce conteneur », et non « le conteneur Ollama ».

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

Réseau hôte (host networking)

network_mode: host peut être tentant sur un serveur mononœud car il supprime la publication des ports et rend la sémantique de localhost plus simple. Le compromis est que vous perdez les avantages d’isolation et de noms (namespacing) d’un réseau en pont, et vous avez plus de chances de rencontrer des conflits de ports.

Exposition intentionnelle d’Ollama

Ollama, lors d’une installation normale, se lie à 127.0.0.1 par défaut, et la méthode documentée pour changer l’adresse de liaison est OLLAMA_HOST.

Dans Docker, vous avez deux couches :

L’adresse de liaison d’Ollama, contrôlée par OLLAMA_HOST (l’image conteneur définit par défaut la liaison sur toutes les interfaces à l’intérieur du conteneur).

L’accessibilité depuis l’extérieur du conteneur, contrôlée par ports de 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 utilisateur ou une extension basée sur le navigateur appelle Ollama directement, vous êtes dans le territoire des CORS. Ollama autorise les requêtes interorigines depuis 127.0.0.1 et 0.0.0.0 par défaut, et vous pouvez configurer des origines supplémentaires à l’aide de OLLAMA_ORIGINS.

Cela compte même sur un nœud unique, car « ça fonctionne avec curl » ne signifie pas « ça fonctionne depuis une application navigateur ».

Modèles de mise à niveau et de retour arrière adaptés à un serveur mononœud

Ollama évolue rapidement. Votre fichier Compose peut en faire un processus calme au lieu d’une surprise en pleine nuit.

Mise à niveau en incrémentant une étiquette, plutôt qu’en espérant que « latest » se comporte bien

La stratégie de mise à niveau la plus pratique est d’épingler l’image à une étiquette connue et bonne dans .env, et de l’incrémenter intentionnellement. L’image est publiée en tant que ollama/ollama sur Docker Hub.

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

Le retour arrière consiste simplement à repasser l’étiquette précédente

Le retour arrière est le même mécanisme en sens inverse : définissez l’étiquette précédente, recréez le conteneur, gardez le même volume. C’est ici que l’épinglage se paie tout seul.

La migration de données porte principalement sur les chemins de stockage

La plupart des « migrations » dans une configuration mononœud ne concernent pas les schémas de base de données. Elles concernent la structure 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 ou non ainsi.

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

Une note finale facile à manquer : la documentation de l’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 à niveau le serveur, garder les clients fonctionnels » une attente par défaut raisonnable pour un point de terminaison de service mononœud.

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

Cette section est délibérément guidée par les symptômes. L’objectif n’est pas « chaque erreur Docker possible », mais seulement 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 en fait mention directement.

Compose ne réserve pas de périphérique GPU. La méthode prise en charge est deploy.resources.reservations.devices avec la capacité gpu comme documenté par Docker.

Une configuration héritée runtime: nvidia est utilisée sur un démon qui ne la 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.

Refus d’accès aux périphériques GPU

La variété « permission denied » des échecs GPU pointe typiquement vers des contraintes d’environnement plutôt que vers Ollama lui-même. Les exemples incluent l’exécution de Docker sans privilèges (rootless), des politiques de sécurité, ou des nœuds de périphériques non exposés comme prévu. La documentation de prise en charge GPU de Docker Compose est explicite : l’hôte doit avoir des périphériques 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 repose sur la pile de pilotes 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 sont en réalité « la pile CUDA n’est pas utilisable ». La documentation officielle place le toolkit conteneur et la configuration du démon Docker comme prérequis pour l’utilisation de GPU NVIDIA.

Épuisement de la mémoire : VRAM ou RAM disparaît rapidement

L’OOM (Out Of Memory) 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 concurrentiel par le biais de multiples modèles chargés et de la gestion parallèle des requêtes, 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 en VRAM pour permettre le chargement concurrentiel des modèles.

Deux détails de configuration méritent d’être traités comme des « paramètres serveur » de premier ordre :

OLLAMA_NUM_PARALLEL augmente le traitement parallèle des requêtes 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 (la valeur par défaut est 5 minutes). Garder les modèles chargés réduit la latence de démarrage à froid, mais il fixe aussi la mémoire.

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

Réduire la concurrence et les valeurs par défaut du contexte avant de changer quoi que ce soit d’autre.

Limiter le nombre de modèles autorisés à rester chargés simultanément.

Envisager les fonctions de réduction de la mémoire comme Flash Attention (OLLAMA_FLASH_ATTENTION=1) et les types de cache K/V de précision réduite (OLLAMA_KV_CACHE_TYPE) lorsque votre goulet d’étranglement est la mémoire, et non la puissance de calcul brute.

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

Parfois, l’« échec » est en réalité un désaccord d’outillage. Si votre organisation standardise déjà sur des artefacts et des flux de travail natifs de Docker, Docker Model Runner (DMR) peut être un meilleur choix que l’exécution d’Ollama en tant que conteneur de service à vie longue.

Docker positionne DMR comme un moyen de gérer, exécuter et servir des modèles directement via Docker, en tirant depuis Docker Hub ou d’autres registres OCI, et en servant des API compatibles OpenAI et compatibles 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 tenez aux caractéristiques de débit, et pas seulement à « exécuter un modèle localement ».

Si vous souhaitez une référence pratique de commandes et un angle de comparaison plus approfondi, voir : Aide-mémoire Docker Model Runner : Commandes & Exemples.

S'abonner

Recevez de nouveaux articles sur les systèmes, l'infrastructure et l'ingénierie IA.