Files
chlova/infra/docker-compose.yml
T
Kantin-Petit 52980837a9 docs: documentation + gate de phase compose, fin Phase 2 (v0.14.0)
docs/need-review.md (cycle complet : états, sursis, gatekeeper, cron,
review, rollback). CHLOVA_PHASE dans .env.example + compose (défaut 1).
risk-tiers + README : application par phase. Compose revalidé, 45 tests,
0 vuln.

Palier de risque : n/a (doc + config).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 01:34:12 +02:00

119 lines
4.5 KiB
YAML

# CHLOVA — stack d'orchestration.
# Règles : une seule surface exposée (backend), tout le reste interne, images
# épinglées (jamais :latest), secrets par référence (voir ../.env.example).
#
# ⚠️ Les tags ci-dessous sont des points d'épinglage à CONFIRMER avant tout
# déploiement réel : `docker pull <image>:<tag>` puis remplacer par
# `<image>:<tag>@sha256:<digest>` pour une immuabilité complète (docs/versioning.md).
# Aucun déploiement réel n'est lancé depuis ce dépôt sans validation explicite.
name: chlova
services:
# ── Ollama : proxy authentifié vers les modèles cloud (ollama.com) ──────
ollama:
image: ollama/ollama:0.6.8 # TODO épingler le digest
restart: unless-stopped
environment:
# Clé du proxy cloud — injectée depuis .env, jamais en dur.
OLLAMA_API_KEY: ${OLLAMA_API_KEY:?OLLAMA_API_KEY requis}
OLLAMA_HOST: 0.0.0.0:11434
volumes:
- ollama-data:/root/.ollama
networks:
- chlova-internal # joignable par le backend
- chlova-egress # seul service autorisé à sortir
# AUCUN port publié : Ollama n'a pas d'auth native, jamais exposé.
# ── socket-proxy : accès Docker filtré (voir socket-proxy/README.md) ────
socket-proxy:
image: tecnativa/docker-socket-proxy:0.3.0 # TODO épingler le digest
restart: unless-stopped
environment:
# Phase 1 — LECTURE SEULE : lecture autorisée, mutation refusée.
CONTAINERS: 1
IMAGES: 1
NETWORKS: 1
VOLUMES: 1
SERVICES: 1
TASKS: 1
NODES: 1
INFO: 1
VERSION: 1
POST: 0 # refuse toute mutation
EXEC: 0 # refuse exec dans un conteneur
AUTH: 0
SECRETS: 0
CONFIGS: 0
BUILD: 0
COMMIT: 0
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro # seul à monter le socket
networks:
- chlova-internal
# AUCUN port publié.
# ── MCP n8n (czlonkowski/n8n-mcp) — read-only en Phase 1 ────────────────
mcp-n8n:
image: ghcr.io/czlonkowski/n8n-mcp:2.18.3 # TODO confirmer tag + épingler digest
restart: unless-stopped
environment:
MCP_MODE: http # transport HTTP (backend distant via réseau)
MCP_AUTH_TOKEN: ${MCP_N8N_AUTH_TOKEN:?requis}
N8N_API_URL: ${N8N_API_URL} # instance n8n existante (interne)
N8N_API_KEY: ${N8N_API_KEY:?requis} # token n8n à portée RESTREINTE (lecture P1)
networks:
- chlova-internal
# AUCUN port publié.
# ── MCP Portainer (portainer/portainer-mcp) — read-only en Phase 1 ──────
mcp-portainer:
image: portainer/portainer-mcp:0.6.0 # TODO confirmer tag/transport + épingler digest
restart: unless-stopped
environment:
PORTAINER_URL: ${PORTAINER_URL}
PORTAINER_MCP_AUTH_TOKEN: ${PORTAINER_MCP_AUTH_TOKEN:?requis}
PORTAINER_READ_ONLY: ${PORTAINER_READ_ONLY:-true} # P1 : NE PAS passer à false
# Docker via socket-proxy uniquement, jamais le socket brut.
DOCKER_HOST: tcp://socket-proxy:2375
depends_on:
- socket-proxy
networks:
- chlova-internal
# AUCUN port publié.
# ── Backend CHLOVA : SEULE surface, cerveau (boucle agent) ──────────────
backend:
build:
context: ../orchestrator # Dockerfile ajouté en Phase 1
image: chlova/backend:0.1.0 # tag versionné local
restart: unless-stopped
env_file: ../.env
environment:
CHLOVA_ENV: ${CHLOVA_ENV:-production}
CHLOVA_PHASE: ${CHLOVA_PHASE:-1} # 1 = lecture seule (défaut) ; 2 = écriture sous review
OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://ollama:11434}
MCP_N8N_URL: ${MCP_N8N_URL:-http://mcp-n8n:3000}
MCP_PORTAINER_URL: ${MCP_PORTAINER_URL:-http://mcp-portainer:3000}
volumes:
- chlova-data:/app/data # SQLite (table assets, P2+)
depends_on:
- ollama
- mcp-n8n
- mcp-portainer
networks:
- chlova-internal
# Phase 1 : surface Telegram en long-polling → AUCUN port publié.
# Phases ultérieures (API/UI) : exposer UNIQUEMENT ce service derrière
# Traefik + TLS et/ou VPN mesh. Voir infra/networks.md.
networks:
chlova-internal:
internal: true # aucune route vers l'extérieur
chlova-egress:
driver: bridge # sortie contrôlée (Ollama → ollama.com), egress filtré côté hôte
volumes:
ollama-data:
chlova-data: