Déploiement d'une stack IA complète avec Docker Compose : orchestration en un clic du LLM à la base de données vectorielle
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
- Déploiement en production avec Docker Compose - 7 stratégies de production des vérifications de santé aux mises à jour sans interruption
- Guide de déploiement en production IA Python - Meilleures pratiques pour le déploiement en production de modèles IA Python
- Guide de durcissement de sécurité Docker - Durcissement de sécurité des conteneurs et protection contre les vulnérabilités
Références externes
- Documentation officielle d'Ollama - Documentation complète du serving de modèles Ollama
- Documentation officielle de Qdrant - Guide de déploiement et d'optimisation de base de données vectorielle
Essayez ces outils exécutés localement dans le navigateur — aucune inscription requise →