Déploiement d'une stack IA complète avec Docker Compose : orchestration en un clic du LLM à la base de données vectorielle

DevOps

Configurer un environnement de développement IA prend encore trois jours ?

En 2026, la configuration de l'environnement de développement IA reste un cauchemar pour les développeurs. Vous devez installer Ollama pour le serving LLM, configurer Qdrant pour le stockage vectoriel, mettre en place des services d'embedding, construire une passerelle API pour l'authentification et gérer les pilotes GPU, les versions CUDA et les téléchargements de modèles... Trois jours passés, et vous n'avez pas écrit une seule ligne de code.

Le déploiement de stack IA complète avec Docker Compose orchestre tout dans un seul fichier. docker compose up -d lance toute la stack IA en quelques minutes. Cet article est un guide pratique complet couvrant 7 modèles fondamentaux, 5 pièges courants, 10 étapes de dépannage et des stratégies de durcissement en production.

Points clés

  • Déploiement de stack IA complète avec Docker Compose = LLM + Base de données vectorielle + Embedding + Passerelle API + Supervision, un fichier pour les gouverner tous
  • Ollama + OpenWebUI est la solution de serving LLM locale la plus mature
  • Qdrant/Milvus sont les bases de données vectorielles de référence avec un déploiement Docker ultra-simple
  • Le passthrough GPU est critique pour le déploiement IA — configurez-le via deploy.resources.reservations.devices
  • La production nécessite l'authentification, la limitation de débit, la supervision et le durcissement des sauvegardes

Table des matières

  • Vue d'ensemble de l'architecture de stack IA complète
  • Modèle 1 : Serving LLM avec Ollama + OpenWebUI
  • Modèle 2 : Bases de données vectorielles Qdrant/Milvus
  • Modèle 3 : Services d'embedding et gestion des modèles
  • Modèle 4 : Passerelle API et authentification
  • Modèle 5 : Passthrough GPU et limites de ressources
  • Modèle 6 : Supervision et observabilité
  • Modèle 7 : Durcissement en production et sécurité
  • 5 pièges courants et solutions
  • 10 dépannages d'erreurs courantes
  • Conseils d'optimisation avancés
  • Comparaison : Docker Compose vs K8s vs Docker Swarm
  • Outils en ligne recommandés
  • Résumé

Vue d'ensemble de l'architecture de stack IA complète

Le déploiement de stack IA complète avec Docker Compose repose sur une architecture à 7 couches, du GPU à la base jusqu'à la passerelle API au sommet :

┌─────────────────────────────────────────────────────┐
│                   API Gateway                        │
│              (Traefik / Nginx)                       │
│         Auth · Rate Limit · Routing · TLS            │
├──────────┬──────────┬──────────┬────────────────────┤
│ OpenWebUI│  RAG App │  Agent   │  Admin Panel       │
│  (Chat)  │ (Search) │  (Proxy) │  (Management)      │
├──────────┴──────────┴──────────┴────────────────────┤
│              Embedding Service                       │
│       (TEI / Infinity / FastEmbed)                  │
├──────────────────┬──────────────────────────────────┤
│   Ollama LLM     │    vLLM / TGI                    │
│  (Model Serving) │  (High-Perf Inference)           │
├──────────────────┴──────────────────────────────────┤
│           Vector Database                            │
│     (Qdrant / Milvus / Weaviate)                    │
├─────────────────────────────────────────────────────┤
│              Infrastructure                          │
│   Redis · PostgreSQL · MinIO · Prometheus            │
├─────────────────────────────────────────────────────┤
│              GPU / CPU Runtime                       │
│     NVIDIA CUDA · ROCm · CPU Fallback               │
└─────────────────────────────────────────────────────┘

Structure de répertoire du projet pour le déploiement de stack IA complète avec Docker Compose :

ai-stack/
├── docker-compose.yml
├── docker-compose.gpu.yml
├── docker-compose.prod.yml
├── .env
├── ollama/
│   └── Modelfile
├── qdrant/
│   └── config.yaml
├── traefik/
│   ├── traefik.yml
│   └── acme.json
├── monitoring/
│   ├── prometheus.yml
│   └── grafana/
│       └── dashboards/
└── scripts/
    ├── init-models.sh
    └── backup-vectors.sh

Modèle 1 : Serving LLM avec Ollama + OpenWebUI

Ollama est la solution de serving LLM locale la plus mature en 2026, prenant en charge Llama 4, Qwen 3, DeepSeek V3 et d'autres modèles mainstream. OpenWebUI fournit une interface web de style ChatGPT.

Configuration de base

services:
  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    ports:
      - "11434:11434"
    volumes:
      - ollama_data:/root/.ollama
    environment:
      OLLAMA_KEEP_ALIVE: "24h"
      OLLAMA_NUM_PARALLEL: "4"
      OLLAMA_MAX_LOADED_MODELS: "3"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    restart: unless-stopped

  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    ports:
      - "3000:8080"
    volumes:
      - open_webui_data:/app/backend/data
    environment:
      OLLAMA_BASE_URL: "http://ollama:11434"
      WEBUI_SECRET_KEY: "${WEBUI_SECRET_KEY}"
      ENABLE_SIGNUP: "false"
      DEFAULT_USER_ROLE: "user"
    depends_on:
      ollama:
        condition: service_healthy
    restart: unless-stopped

volumes:
  ollama_data:
  open_webui_data:

Téléchargement automatique des modèles

Après avoir démarré Ollama, vous devez télécharger les modèles manuellement. Automatisez cela avec un script d'initialisation :

#!/bin/bash
# scripts/init-models.sh

MODELS=(
  "qwen3:8b"
  "llama4:8b"
  "deepseek-v3:8b"
  "nomic-embed-text"
)

for model in "${MODELS[@]}"; do
  echo "Pulling model: $model"
  until curl -s http://localhost:11434/api/pull -d "{\"name\":\"$model\"}" | grep -q "success"; do
    echo "  Retrying $model..."
    sleep 5
  done
  echo "  ✓ $model ready"
done

echo "All models pulled successfully!"

Ajoutez le service d'initialisation à Docker Compose :

  model-init:
    image: curlimages/curl:latest
    container_name: model-init
    depends_on:
      ollama:
        condition: service_healthy
    volumes:
      - ./scripts/init-models.sh:/init-models.sh:ro
    entrypoint: ["/bin/sh", "/init-models.sh"]
    restart: "no"

Modelfile personnalisé

# ollama/Modelfile
FROM qwen3:8b

PARAMETER temperature 0.7
PARAMETER top_p 0.9
PARAMETER num_ctx 8192
PARAMETER stop "<|im_end|>"

SYSTEM """
You are a professional AI assistant. When answering questions:
1. Give a concise conclusion first
2. Then provide detailed explanation
3. If uncertain, say so explicitly
"""

Construisez un modèle personnalisé :

docker exec ollama ollama create my-assistant -f /root/.ollama/Modelfile

Modèle 2 : Bases de données vectorielles Qdrant/Milvus

Les bases de données vectorielles sont le cœur de l'architecture RAG. Le déploiement de stack IA complète avec Docker Compose utilise généralement Qdrant (léger) ou Milvus (à grande échelle).

Configuration de Qdrant (Recommandé pour les projets petite-moyenne taille)

  qdrant:
    image: qdrant/qdrant:latest
    container_name: qdrant
    ports:
      - "6333:6333"
      - "6334:6334"
    volumes:
      - qdrant_data:/qdrant/storage
      - ./qdrant/config.yaml:/qdrant/config/production.yaml:ro
    environment:
      QDRANT__SERVICE__GRPC_PORT: "6334"
      QDRANT__LOG_LEVEL: "INFO"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:6333/healthz"]
      interval: 10s
      timeout: 5s
      retries: 3
    restart: unless-stopped

Fichier de configuration de Qdrant :

# qdrant/config.yaml
storage:
  performance:
    max_search_threads: 4
  wal:
    wal_capacity_mb: 32
    wal_segments_ahead: 0
  optimizers:
    indexing_threshold: 20000
    memmap_threshold: 50000
service:
  max_request_size_mb: 64
  enable_cors: true
telemetry_disabled: true

Configuration de Milvus (Recommandé pour les projets à grande échelle)

  etcd:
    image: quay.io/coreos/etcd:v3.5.16
    container_name: milvus-etcd
    environment:
      ETCD_AUTO_COMPACTION_MODE: "revision"
      ETCD_AUTO_COMPACTION_RETENTION: "1000"
      ETCD_QUOTA_BACKEND_BYTES: "4294967296"
    volumes:
      - etcd_data:/etcd
    command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379
    restart: unless-stopped

  minio:
    image: minio/minio:latest
    container_name: milvus-minio
    environment:
      MINIO_ACCESS_KEY: "${MINIO_ACCESS_KEY}"
      MINIO_SECRET_KEY: "${MINIO_SECRET_KEY}"
    ports:
      - "9001:9001"
      - "9000:9000"
    volumes:
      - minio_data:/minio_data
    command: minio server /minio_data --console-address ":9001"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3
    restart: unless-stopped

  milvus:
    image: milvusdb/milvus:v2.5-latest
    container_name: milvus
    ports:
      - "19530:19530"
      - "9091:9091"
    volumes:
      - milvus_data:/var/lib/milvus
    environment:
      ETCD_ENDPOINTS: "etcd:2379"
      MINIO_ADDRESS: "minio:9000"
    depends_on:
      - etcd
      - minio
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
      interval: 30s
      timeout: 20s
      retries: 3
      start_period: 90s
    restart: unless-stopped

Comparaison des bases de données vectorielles

Caractéristique Qdrant Milvus Weaviate ChromaDB
Complexité de déploiement Très faible (1 conteneur) Élevée (3+ conteneurs) Faible (1 conteneur) Très faible (1 conteneur)
Performance (Millions) Excellente Excellente Bonne Passable
Performance (Milliards) Bonne Excellente Passable N/A
Recherche filtrée ✅ Puissante ✅ Puissante ✅ Bonne ⚠️ Basique
Persistance ⚠️ En mémoire par défaut
Multi-réplica
Support gRPC
Compatibilité Docker Compose ✅ Meilleure ⚠️ Lourd ✅ Bonne ✅ Développement uniquement
Prêt pour la production ❌ Développement uniquement

Recommandation : Pour le déploiement de stack IA complète avec Docker Compose, Qdrant est le premier choix — déploiement simple, performance excellente. Envisagez Milvus lorsque le nombre de vecteurs dépasse 100 millions. ChromaDB convient uniquement au prototypage.


Modèle 3 : Services d'embedding et gestion des modèles

Les services d'embedding convertissent le texte en vecteurs, une étape critique dans le pipeline RAG. L'orchestration de conteneurs Docker Compose AI offre trois solutions principales.

Hugging Face TEI (Recommandé)

  tei:
    image: ghcr.io/huggingface/text-embeddings-inference:latest
    container_name: tei
    ports:
      - "8080:80"
    volumes:
      - tei_cache:/data
    environment:
      MODEL_ID: "BAAI/bge-m3"
      REVISION: "main"
      MAX_BATCH_TOKENS: "16384"
      MAX_CLIENT_BATCH_SIZE: "32"
      HF_TOKEN: "${HF_TOKEN}"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:80/health"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 120s
    restart: unless-stopped

Service d'embedding Infinity

  infinity:
    image: michaelf34/infinity:latest
    container_name: infinity
    ports:
      - "7997:7997"
    volumes:
      - infinity_cache:/app/.cache
    environment:
      MODEL_ID: "BAAI/bge-m3"
      ENGINE: "optimum"
      BATCH_SIZE: "32"
    command: >
      --model-id BAAI/bge-m3
      --engine optimum
      --port 7997
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7997/health"]
      interval: 10s
      timeout: 5s
      retries: 3
    restart: unless-stopped

Exemple d'utilisation du service d'embedding

import httpx
import numpy as np

async def get_embeddings(texts: list[str]) -> list[list[float]]:
    async with httpx.AsyncClient(timeout=30.0) as client:
        response = await client.post(
            "http://tei:80/embed",
            json={"inputs": texts}
        )
        response.raise_for_status()
        return response.json()

async def search_similar(query: str, top_k: int = 5) -> list[dict]:
    query_embedding = await get_embeddings([query])
    async with httpx.AsyncClient(timeout=30.0) as client:
        response = await client.post(
            "http://qdrant:6333/collections/documents/points/search",
            json={
                "vector": query_embedding[0],
                "limit": top_k,
                "with_payload": True
            }
        )
        response.raise_for_status()
        return response.json()["result"]

Comparaison des services d'embedding

Caractéristique TEI Infinity FastEmbed
Accélération GPU ✅ Native ✅ Native ❌ CPU uniquement
Inférence par lot ✅ Efficace ✅ Efficace ⚠️ Passable
Multi-modèles
Taille de l'image Docker ~2Go ~4Go ~500Mo
Prêt pour la production ⚠️ Développement uniquement
API compatible OpenAI

Modèle 4 : Passerelle API et authentification

Le déploiement de stack IA complète avec Docker Compose en production nécessite une passerelle API pour l'authentification unifiée, la limitation de débit et le routage.

Configuration de Traefik

  traefik:
    image: traefik:v3.2
    container_name: traefik
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro
      - traefik_certs:/etc/traefik/certs
      - ./traefik/dynamic:/etc/traefik/dynamic:ro
    command:
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.file.directory=/etc/traefik/dynamic"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
    labels:
      traefik.enable: "true"
      traefik.http.routers.traefik.rule: "Host(`traefik.ai-stack.local`)"
      traefik.http.routers.traefik.entrypoints: "websecure"
      traefik.http.routers.traefik.tls: "true"
      traefik.http.services.traefik.loadbalancer.server.port: "8080"
    restart: unless-stopped

OpenWebUI avec Traefik

  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    volumes:
      - open_webui_data:/app/backend/data
    environment:
      OLLAMA_BASE_URL: "http://ollama:11434"
    labels:
      traefik.enable: "true"
      traefik.http.routers.webui.rule: "Host(`chat.ai-stack.local`)"
      traefik.http.routers.webui.entrypoints: "websecure"
      traefik.http.routers.webui.tls: "true"
      traefik.http.services.webui.loadbalancer.server.port: "8080"
    depends_on:
      ollama:
        condition: service_healthy
    restart: unless-stopped

Middleware d'authentification

# traefik/dynamic/auth.yml
http:
  middlewares:
    auth-middleware:
      forwardAuth:
        address: "http://auth-service:8000/verify"
        trustForwardHeader: true
        authResponseHeaders:
          - "X-User-Id"
          - "X-User-Role"

    rate-limit:
      rateLimit:
        average: 30
        burst: 60
        period: 1m

  routers:
    api-router:
      rule: "Host(`api.ai-stack.local`)"
      entrypoints:
        - "websecure"
      tls: true
      middlewares:
        - "auth-middleware"
        - "rate-limit"
      service: "ollama-api"

Modèle 5 : Passthrough GPU et limites de ressources

Le GPU est le cœur du déploiement IA. Le déploiement de stack IA complète avec Docker Compose active le passthrough GPU via deploy.resources.reservations.devices.

Passthrough GPU NVIDIA

  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    volumes:
      - ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
        limits:
          memory: 16G
          cpus: "8.0"
    environment:
      NVIDIA_VISIBLE_DEVICES: "all"
      NVIDIA_DRIVER_CAPABILITIES: "compute,utility"
      OLLAMA_KEEP_ALIVE: "24h"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped

Allocation multi-GPU

  ollama:
    image: ollama/ollama:latest
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              device_ids: ["0"]
              capabilities: [gpu]
    environment:
      CUDA_VISIBLE_DEVICES: "0"

  tei:
    image: ghcr.io/huggingface/text-embeddings-inference:latest
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              device_ids: ["1"]
              capabilities: [gpu]
    environment:
      CUDA_VISIBLE_DEVICES: "1"

Configuration de repli CPU

  ollama-cpu:
    image: ollama/ollama:latest
    profiles: ["cpu-only"]
    container_name: ollama
    volumes:
      - ollama_data:/root/.ollama
    environment:
      OLLAMA_NUM_PARALLEL: "2"
      OLLAMA_MAX_LOADED_MODELS: "1"
    deploy:
      resources:
        limits:
          memory: 8G
          cpus: "4.0"

  ollama-gpu:
    image: ollama/ollama:latest
    profiles: ["gpu"]
    container_name: ollama
    volumes:
      - ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
        limits:
          memory: 16G

Commandes de lancement :

# Mode GPU
docker compose --profile gpu up -d

# Mode CPU
docker compose --profile cpu-only up -d

Script de surveillance des ressources GPU

import subprocess
import json
import time

def monitor_gpu_usage(interval: int = 60):
    while True:
        result = subprocess.run(
            ["nvidia-smi", "--query-gpu=index,name,memory.used,memory.total,utilization.gpu",
             "--format=csv,noheader,nounits"],
            capture_output=True, text=True
        )
        for line in result.stdout.strip().split("\n"):
            idx, name, mem_used, mem_total, util = line.split(", ")
            print(f"GPU {idx} ({name}): {mem_used}/{mem_total}MB, Util: {util}%")
        time.sleep(interval)

if __name__ == "__main__":
    monitor_gpu_usage()

Modèle 6 : Supervision et observabilité

La supervision du déploiement de stack IA complète avec Docker Compose doit couvrir l'utilisation du GPU, la latence d'inférence, les performances de la base de données vectorielle et d'autres métriques spécifiques à l'IA.

Prometheus + Grafana

  prometheus:
    image: prom/prometheus:v3.2.0
    container_name: prometheus
    volumes:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus_data:/prometheus
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.retention.time=30d"
      - "--storage.tsdb.retention.size=10GB"
    ports:
      - "9090:9090"
    restart: unless-stopped

  grafana:
    image: grafana/grafana:11.5.0
    container_name: grafana
    volumes:
      - grafana_data:/var/lib/grafana
      - ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
      - ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources:ro
    environment:
      GF_SECURITY_ADMIN_USER: "${GRAFANA_USER}"
      GF_SECURITY_ADMIN_PASSWORD: "${GRAFANA_PASSWORD}"
      GF_USERS_ALLOW_SIGN_UP: "false"
    ports:
      - "3001:3000"
    depends_on:
      - prometheus
    restart: unless-stopped

  dcgm-exporter:
    image: nvidia/dcgm-exporter:latest
    container_name: dcgm-exporter
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    ports:
      - "9400:9400"
    restart: unless-stopped

Configuration de Prometheus

# monitoring/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: "ollama"
    static_configs:
      - targets: ["ollama:11434"]
    metrics_path: "/metrics"
    scrape_interval: 30s

  - job_name: "qdrant"
    static_configs:
      - targets: ["qdrant:6333"]
    metrics_path: "/metrics"
    scrape_interval: 30s

  - job_name: "dcgm"
    static_configs:
      - targets: ["dcgm-exporter:9400"]
    scrape_interval: 10s

  - job_name: "node-exporter"
    static_configs:
      - targets: ["node-exporter:9100"]

  - job_name: "traefik"
    static_configs:
      - targets: ["traefik:8080"]

Règles d'alerte clés

# monitoring/alerts.yml
groups:
  - name: ai-stack
    rules:
      - alert: OllamaHighLatency
        expr: histogram_quantile(0.95, rate(ollama_request_duration_seconds_bucket[5m])) > 30
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Latence d'inférence Ollama trop élevée"

      - alert: GPUMemoryHigh
        expr: DCGM_FI_DEV_FB_USED / DCGM_FI_DEV_FB_TOTAL > 0.9
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "L'utilisation de la mémoire GPU dépasse 90%"

      - alert: QdrantHighLatency
        expr: histogram_quantile(0.95, rate(qdrant_request_duration_seconds_bucket[5m])) > 5
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Latence de requête Qdrant trop élevée"

      - alert: OllamaContainerDown
        expr: up{job="ollama"} == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Service Ollama indisponible"

Modèle 7 : Durcissement en production et sécurité

La sécurité est la ligne de base pour le déploiement de stack IA complète avec Docker Compose en production.

Gestion des secrets

services:
  ollama:
    image: ollama/ollama:latest
    secrets:
      - hf_token
    environment:
      HF_TOKEN_FILE: /run/secrets/hf_token

  qdrant:
    image: qdrant/qdrant:latest
    secrets:
      - qdrant_api_key
    environment:
      QDRANT__SERVICE__API_KEY_FILE: /run/secrets/qdrant_api_key

secrets:
  hf_token:
    file: ./secrets/hf_token.txt
  qdrant_api_key:
    file: ./secrets/qdrant_api_key.txt
  db_password:
    file: ./secrets/db_password.txt

Isolation réseau

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true
  monitoring:
    driver: bridge
    internal: true

services:
  traefik:
    networks:
      - frontend
      - backend

  open-webui:
    networks:
      - frontend
      - backend

  ollama:
    networks:
      - backend

  qdrant:
    networks:
      - backend

  tei:
    networks:
      - backend

  prometheus:
    networks:
      - monitoring
      - backend

  grafana:
    networks:
      - frontend
      - monitoring

Stratégie de sauvegarde

#!/bin/bash
# scripts/backup-vectors.sh

BACKUP_DIR="/backups/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"

echo "Backing up Qdrant..."
curl -s -X POST "http://localhost:6333/snapshots" | jq .

echo "Backing up Ollama models list..."
curl -s "http://localhost:11434/api/tags" | jq . > "$BACKUP_DIR/ollama_models.json"

echo "Backing up environment config..."
cp .env "$BACKUP_DIR/.env.backup"
cp docker-compose.yml "$BACKUP_DIR/docker-compose.yml.backup"

echo "Backup completed: $BACKUP_DIR"

Configuration complète de production

# docker-compose.prod.yml
services:
  ollama:
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
        limits:
          memory: 16G
          cpus: "8.0"
      restart_policy:
        condition: on-failure
        delay: 10s
        max_attempts: 5
        window: 120s
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "5"
    read_only: true
    tmpfs:
      - /tmp

  qdrant:
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: "2.0"
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"

5 pièges courants et solutions

Piège 1 : Délai d'attente dépassé lors du téléchargement des modèles Ollama

Symptôme : Après docker compose up, Ollama reste bloqué lors du téléchargement des modèles. Les grands modèles (ex., Llama 4 70B) peuvent prendre plus d'une heure à télécharger.

Solution : Utilisez le service model-init pour le téléchargement asynchrone. Le service Ollama lui-même n'a pas besoin d'attendre les modèles.

  model-init:
    image: curlimages/curl:latest
    depends_on:
      ollama:
        condition: service_healthy
    volumes:
      - ./scripts/init-models.sh:/init-models.sh:ro
    entrypoint: ["/bin/sh", "/init-models.sh"]
    restart: "no"
    deploy:
      resources:
        limits:
          memory: 256M

Piège 2 : OOM du conteneur Qdrant

Symptôme : À mesure que les données vectorielles augmentent, le conteneur Qdrant est OOM Killed.

Solution : Définissez des limites de mémoire et activez le mappage mémoire.

  qdrant:
    image: qdrant/qdrant:latest
    deploy:
      resources:
        limits:
          memory: 8G
    environment:
      QDRANT__STORAGE__PERFORMANCE__MAX_SEARCH_THREADS: "4"
      QDRANT__STORAGE__WAL__WAL_CAPACITY_MB: "64"

Piège 3 : Incompatibilité de version du pilote GPU

Symptôme : docker compose up affiche l'erreur CUDA driver version is insufficient.

Solution : Assurez-vous que le pilote NVIDIA de l'hôte est ≥ 535, installez nvidia-container-toolkit.

# Vérifier la version du pilote
nvidia-smi | head -3

# Installer nvidia-container-toolkit (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-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

Piège 4 : Service d'embedding et LLM en compétition pour le GPU

Symptôme : Mémoire GPU insuffisante lorsque TEI et Ollama fonctionnent simultanément ; le chargement du modèle échoue.

Solution : Utilisez device_ids pour une allocation GPU précise, ou exécutez le service d'embedding sur le CPU.

  ollama:
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              device_ids: ["0"]
              capabilities: [gpu]

  tei:
    # Exécuter le service d'embedding en mode CPU
    environment:
      MODEL_ID: "BAAI/bge-m3"
      # Pas d'allocation GPU, utilise le CPU

Piège 5 : Échec de résolution DNS inter-conteneurs

Symptôme : OpenWebUI signale ollama: Name or service not known.

Solution : Assurez-vous que tous les services sont sur le même réseau, utilisez container_name ou le nom du service comme nom d'hôte.

networks:
  ai-network:
    driver: bridge

services:
  ollama:
    container_name: ollama
    networks:
      - ai-network

  open-webui:
    container_name: open-webui
    networks:
      - ai-network
    environment:
      OLLAMA_BASE_URL: "http://ollama:11434"

10 dépannages d'erreurs courantes

1. could not select device driver — Runtime NVIDIA non installé

# Installer nvidia-container-toolkit et redémarrer Docker
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
docker info | grep -i runtime
# Devrait afficher le runtime nvidia

2. OOM Killed — Mémoire GPU insuffisante

# Vérifier la mémoire GPU
nvidia-smi
# Utiliser des modèles plus petits ou quantifiés
docker exec ollama ollama run qwen3:4b

3. Connection refused vers Ollama — Service non prêt

# Vérifier l'état de santé d'Ollama
docker compose ps
docker compose logs ollama
# Attendre que le healthcheck passe avant de se connecter

4. permission denied sur le socket Docker

sudo usermod -aG docker $USER
newgrp docker

5. Qdrant collection not found — Collection non créée

curl -X PUT "http://localhost:6333/collections/documents" \
  -H "Content-Type: application/json" \
  -d '{"vectors": {"size": 1024, "distance": "Cosine"}}'

6. model not found — Modèle Ollama non téléchargé

docker exec ollama ollama pull qwen3:8b

7. CUDA out of memory — Dépassement de mémoire GPU pendant l'inférence

# Réduire les requêtes parallèles
# Configurer dans docker-compose.yml
environment:
  OLLAMA_NUM_PARALLEL: "1"
  OLLAMA_MAX_LOADED_MODELS: "1"

8. TLS handshake error — Problème de certificat Traefik

# Vérifier les permissions du fichier de certificat
chmod 600 traefik/acme.json
# Vérifier les logs Traefik
docker compose logs traefik

9. too many open files — Limite de descripteurs de fichiers

# Augmenter temporairement la limite
ulimit -n 65536
# Configuration permanente (/etc/security/limits.conf)
# * soft nofile 65536
# * hard nofile 65536

10. vector dimension mismatch — Incohérence de dimensions d'embedding

# S'assurer que la dimension de la collection Qdrant correspond à la sortie du modèle d'embedding
# bge-m3 : 1024 dimensions
# nomic-embed-text : 768 dimensions
curl -X PUT "http://localhost:6333/collections/documents" \
  -d '{"vectors": {"size": 1024, "distance": "Cosine"}}'

Conseils d'optimisation avancés

Réchauffement de modèles en plusieurs étapes

  model-warmer:
    image: curlimages/curl:latest
    container_name: model-warmer
    depends_on:
      ollama:
        condition: service_healthy
    entrypoint: >
      /bin/sh -c "
        echo 'Warming up models...' &&
        curl -s http://ollama:11434/api/generate -d '{\"model\":\"qwen3:8b\",\"prompt\":\"hi\",\"stream\":false}' > /dev/null &&
        curl -s http://ollama:11434/api/generate -d '{\"model\":\"nomic-embed-text\",\"prompt\":\"test\",\"stream\":false}' > /dev/null &&
        echo 'Models warmed up!'
      "
    restart: "no"

Déchargement intelligent des modèles

  ollama:
    environment:
      OLLAMA_KEEP_ALIVE: "5m"
      OLLAMA_NUM_PARALLEL: "4"
      OLLAMA_MAX_LOADED_MODELS: "2"

OLLAMA_KEEP_ALIVE: "5m" décharge automatiquement les modèles inactifs pendant 5 minutes, libérant la mémoire GPU.

Dépendances chaînées de vérifications de santé

  tei:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:80/health"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 120s

  qdrant:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:6333/healthz"]
      interval: 10s
      timeout: 5s
      retries: 3

  rag-app:
    depends_on:
      ollama:
        condition: service_healthy
      tei:
        condition: service_healthy
      qdrant:
        condition: service_healthy

Docker Compose Watch pour le développement

# docker-compose.yml
services:
  rag-app:
    build: .
    develop:
      watch:
        - action: rebuild
          path: ./app
          target: /app
        - action: sync
          path: ./app/static
          target: /app/static

Comparaison : Docker Compose vs K8s vs Docker Swarm

Dimension Docker Compose Kubernetes Docker Swarm
Complexité de déploiement de stack IA ⭐ Très faible ⭐⭐⭐⭐⭐ Très élevée ⭐⭐ Faible
Ordonnancement GPU ✅ Natif ✅ Device Plugin ⚠️ Nécessite configuration
Auto-scaling ✅ HPA ⚠️ Manuel
Découverte de services ✅ DNS ✅ CoreDNS ✅ DNS
Mises à jour continues ⚠️ Nécessite des scripts ✅ Natif ✅ Natif
Gestion de configuration ✅ .env ✅ ConfigMap ⚠️ Config
Gestion des secrets ✅ Docker Secret ✅ K8s Secret ⚠️ Basique
Écosystème de supervision ✅ Prometheus ✅ Complet ⚠️ Limité
Orchestration multi-nœuds ❌ Nœud unique ✅ Capacité centrale ✅ Natif
Courbe d'apprentissage Faible Élevée Faible
Activité de la communauté ✅ Active ✅ Très active ❌ En déclin
Échelle de projet IA adaptée 1-5 GPU 10+ GPU 2-5 GPU

Recommandation : Le déploiement de stack IA complète avec Docker Compose est idéal pour les scénarios à machine unique avec 1-5 GPU — le meilleur choix pour le développement IA et la production à petite échelle. Pour 5+ GPU ou des besoins multi-nœuds, envisagez Kubernetes + KServe/vLLM. Docker Swarm n'est pas recommandé pour le déploiement IA.


Outils en ligne recommandés

  • Formateur JSON - Formater les données JSON de Docker Compose et des réponses API
  • Encodage Base64 - Encoder les configurations de Secrets et API Key
  • cURL vers Code - Convertir les commandes cURL Qdrant/Ollama en code Python/JS

Résumé

Le déploiement de stack IA complète avec Docker Compose transforme les environnements de développement IA de « trois jours pour configurer » à « une commande pour lancer ». Ollama + OpenWebUI gère le serving LLM, Qdrant gère le stockage vectoriel, TEI gère les embeddings, Traefik gère la passerelle, Prometheus + Grafana gère la supervision, et le passthrough GPU fait voler l'inférence. 7 modèles couvrent toute la chaîne du développement à la production, 5 pièges courants et 10 étapes de dépannage vous aident à éviter les détours. Pour les projets IA avec 1-5 GPU, Docker Compose est la solution d'orchestration de conteneurs IA la plus pratique en 2026.

Articles connexes

Références externes

Essayez ces outils exécutés localement dans le navigateur — aucune inscription requise →

#Docker#Docker Compose#AI部署#LLM#向量数据库#Ollama#2026#DevOps