Some checks failed
E2E Tests / e2e (push) Failing after 19s
Build & Push Images / build (brain) (push) Successful in 59s
Build & Push Images / build (core) (push) Successful in 1m32s
Build & Push Images / build-switcher (push) Successful in 43s
Build & Push Images / build (web) (push) Successful in 1m36s
271 lines
12 KiB
YAML
271 lines
12 KiB
YAML
# ==========================================================================
|
|
# LoreMindMJ - Stack complete pour distribution utilisateur
|
|
# --------------------------------------------------------------------------
|
|
# Lancement : docker compose up -d
|
|
# Acces : http://localhost:8081
|
|
# Mise a jour: docker compose pull && docker compose up -d
|
|
# ==========================================================================
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
container_name: loremind-postgres
|
|
environment:
|
|
POSTGRES_DB: ${POSTGRES_DB:-loremind}
|
|
POSTGRES_USER: ${POSTGRES_USER:-loremind}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
|
|
volumes:
|
|
- postgres-data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-loremind}"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
restart: unless-stopped
|
|
|
|
minio:
|
|
image: minio/minio:latest
|
|
container_name: loremind-minio
|
|
environment:
|
|
MINIO_ROOT_USER: ${MINIO_USER:-minioadmin}
|
|
MINIO_ROOT_PASSWORD: ${MINIO_PASSWORD:-minioadmin}
|
|
volumes:
|
|
- minio-data:/data
|
|
# Mapping bind sur loopback pour autoriser un core/web lance en local (mode dev)
|
|
# a atteindre MinIO. Invisible sur le LAN donc non-exploitable depuis l'exterieur.
|
|
ports:
|
|
- "127.0.0.1:9000:9000"
|
|
- "127.0.0.1:9001:9001"
|
|
command: server /data --console-address ":9001"
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
|
|
# Creation automatique du bucket loremind-images au premier lancement.
|
|
minio-init:
|
|
image: minio/mc:latest
|
|
container_name: loremind-minio-init
|
|
depends_on:
|
|
minio:
|
|
condition: service_healthy
|
|
entrypoint: >
|
|
/bin/sh -c "
|
|
mc alias set local http://minio:9000 ${MINIO_USER:-minioadmin} ${MINIO_PASSWORD:-minioadmin} &&
|
|
mc mb --ignore-existing local/loremind-images &&
|
|
mc anonymous set download local/loremind-images &&
|
|
echo 'Bucket loremind-images pret.'
|
|
"
|
|
|
|
core:
|
|
# Defaut : GHCR (registry public, reputation domaine elevee).
|
|
# Pour les anciennes installs qui pointaient sur Gitea, REGISTRY et
|
|
# IMAGE_NAMESPACE peuvent etre overrides dans .env :
|
|
# REGISTRY=git.igmlcreation.fr
|
|
# IMAGE_NAMESPACE=ietm64/ (le slash final est important : voir image: ci-dessous)
|
|
image: ${REGISTRY:-ghcr.io}/${IMAGE_NAMESPACE:-igmlcreation/loremind-}core:${TAG:-latest}
|
|
container_name: loremind-core
|
|
labels:
|
|
- "com.centurylinklabs.watchtower.enable=true"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
minio:
|
|
condition: service_healthy
|
|
environment:
|
|
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/${POSTGRES_DB:-loremind}
|
|
SPRING_DATASOURCE_USERNAME: ${POSTGRES_USER:-loremind}
|
|
SPRING_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD}
|
|
APP_CORS_ALLOWED_ORIGINS: http://localhost:${WEB_PORT:-8081}
|
|
BRAIN_BASE_URL: http://brain:8000
|
|
BRAIN_INTERNAL_SECRET: ${BRAIN_INTERNAL_SECRET:?set BRAIN_INTERNAL_SECRET in .env}
|
|
ADMIN_USERNAME: ${ADMIN_USERNAME:-admin}
|
|
ADMIN_PASSWORD: ${ADMIN_PASSWORD:?set ADMIN_PASSWORD in .env}
|
|
MINIO_ENDPOINT: http://minio:9000
|
|
MINIO_ACCESS_KEY: ${MINIO_USER:-minioadmin}
|
|
MINIO_SECRET_KEY: ${MINIO_PASSWORD:-minioadmin}
|
|
# Detection des mises a jour : interroge le registry et delegue le pull/restart
|
|
# a Watchtower. Si WATCHTOWER_TOKEN est vide, la feature est desactivee
|
|
# (l'UI masque le badge et le bouton).
|
|
UPDATE_CHECK_REGISTRY: ${REGISTRY:-ghcr.io}
|
|
UPDATE_CHECK_IMAGES: ${IMAGE_NAMESPACE:-igmlcreation/loremind-}core,${IMAGE_NAMESPACE:-igmlcreation/loremind-}brain,${IMAGE_NAMESPACE:-igmlcreation/loremind-}web
|
|
UPDATE_CHECK_TAG: ${TAG:-latest}
|
|
WATCHTOWER_URL: http://watchtower:8080
|
|
WATCHTOWER_TOKEN: ${WATCHTOWER_TOKEN:-}
|
|
# Licensing : la cle publique JWT est embarquee dans le binaire
|
|
# (core/src/main/resources/licensing/jwt-public-key.pem).
|
|
# LICENSING_JWT_PUBLIC_KEY est un override optionnel (rotation de cle
|
|
# sans rebuild) - non defini par defaut.
|
|
LICENSING_JWT_PUBLIC_KEY: ${LICENSING_JWT_PUBLIC_KEY:-}
|
|
LICENSING_RELAY_BASE_URL: ${LICENSING_RELAY_BASE_URL:-https://loremind-auth.igmlcreation.fr}
|
|
# Chemin du docker config.json partage avec Watchtower
|
|
LICENSING_DOCKER_CONFIG_PATH: /shared/docker/config.json
|
|
# Chemin du repertoire partage avec le switcher (commande + resultat).
|
|
# Doit matcher le volume `switcher-data` monte ci-dessous.
|
|
SWITCHER_DATA_PATH: /shared/switcher
|
|
volumes:
|
|
# Volume partage avec Watchtower : Core ecrit les credentials registry
|
|
# GHCR (recus du relais) ici, Watchtower les utilise pour pull les images
|
|
# privees du canal beta. Pas de creds = no-op.
|
|
- docker-config:/shared/docker
|
|
# Volume partage avec le switcher : Core ecrit une commande de switch
|
|
# de canal ici (command.json), le switcher la traite et y depose son
|
|
# resultat (result.json). Cf. service `switcher` ci-dessous.
|
|
- switcher-data:/shared/switcher
|
|
restart: unless-stopped
|
|
|
|
# Ollama embarque (option par defaut pour les utilisateurs sans Ollama installe).
|
|
# Active via COMPOSE_PROFILES=local-ollama (gere par l'installeur).
|
|
# Si l'utilisateur a deja Ollama sur l'hote, ce service reste inactif et
|
|
# OLLAMA_BASE_URL pointe vers http://host.docker.internal:11434.
|
|
ollama:
|
|
image: ollama/ollama:latest
|
|
container_name: loremind-ollama
|
|
profiles: ["local-ollama"]
|
|
volumes:
|
|
- ollama-data:/root/.ollama
|
|
# Port expose sur loopback uniquement pour debug / pull manuel de modeles.
|
|
ports:
|
|
- "127.0.0.1:11434:11434"
|
|
# GPU NVIDIA si disponible (silencieusement ignore sinon).
|
|
deploy:
|
|
resources:
|
|
reservations:
|
|
devices:
|
|
- driver: nvidia
|
|
count: all
|
|
capabilities: [gpu]
|
|
restart: unless-stopped
|
|
|
|
brain:
|
|
image: ${REGISTRY:-ghcr.io}/${IMAGE_NAMESPACE:-igmlcreation/loremind-}brain:${TAG:-latest}
|
|
container_name: loremind-brain
|
|
labels:
|
|
- "com.centurylinklabs.watchtower.enable=true"
|
|
environment:
|
|
LLM_PROVIDER: ${LLM_PROVIDER:-ollama}
|
|
# Defaut = Ollama embarque (service ollama du compose).
|
|
# L'installeur reecrit cette valeur en http://host.docker.internal:11434
|
|
# si l'utilisateur choisit le mode "Ollama deja installe sur l'hote".
|
|
OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://ollama:11434}
|
|
LLM_MODEL: ${LLM_MODEL:-gemma4:26b}
|
|
ONEMIN_API_KEY: ${ONEMIN_API_KEY:-}
|
|
ONEMIN_MODEL: ${ONEMIN_MODEL:-gpt-4o-mini}
|
|
INTERNAL_SHARED_SECRET: ${BRAIN_INTERNAL_SECRET:?set BRAIN_INTERNAL_SECRET in .env}
|
|
volumes:
|
|
- brain-data:/app/data
|
|
extra_hosts:
|
|
# Linux : permet au conteneur d'atteindre Ollama sur l'hote.
|
|
# Mac/Windows Docker Desktop le fait nativement.
|
|
- "host.docker.internal:host-gateway"
|
|
restart: unless-stopped
|
|
|
|
web:
|
|
image: ${REGISTRY:-ghcr.io}/${IMAGE_NAMESPACE:-igmlcreation/loremind-}web:${TAG:-latest}
|
|
container_name: loremind-web
|
|
labels:
|
|
- "com.centurylinklabs.watchtower.enable=true"
|
|
depends_on:
|
|
- core
|
|
- brain
|
|
ports:
|
|
- "${WEB_PORT:-8081}:80"
|
|
restart: unless-stopped
|
|
|
|
# Sidecar de bascule de canal (stable <-> beta).
|
|
#
|
|
# Pourquoi : la bascule entre canaux change le PREFIXE d'image (loremind- vs
|
|
# loremind-beta-), donc Watchtower seul ne peut pas la faire — il met a jour
|
|
# des images, pas leur reference. Ce sidecar fait le `sed .env` + le
|
|
# `docker compose pull/up -d` quand le Core depose une commande JSON.
|
|
#
|
|
# Securite : pas de port expose. La commande arrive via volume partage
|
|
# (`switcher-data`) que SEUL le Core ecrit. Le switcher valide strictement
|
|
# le contenu (channel ∈ {stable, beta}, rien d'autre) — pas de RCE via
|
|
# compromission du Core.
|
|
#
|
|
# L'image switcher est volontairement HORS de IMAGE_NAMESPACE : elle reste
|
|
# `igmlcreation/loremind-switcher` sur les deux canaux. Sinon le switcher
|
|
# se tuerait lui-meme pendant le `docker compose up -d` (race condition).
|
|
switcher:
|
|
image: ghcr.io/igmlcreation/loremind-switcher:${SWITCHER_TAG:-latest}
|
|
container_name: loremind-switcher
|
|
# PAS de label watchtower : la maj du switcher se fait via le canal
|
|
# stable uniquement, et hors du flow d'auto-update.
|
|
volumes:
|
|
# Socket Docker du host : permet de lancer docker compose pull/up.
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
# Repertoire compose du host (docker-compose.yml + .env) — RW pour
|
|
# pouvoir sed la ligne IMAGE_NAMESPACE.
|
|
- ${COMPOSE_PROJECT_DIR:-./}:/compose
|
|
# Volume partage avec le Core pour la commande + le resultat.
|
|
- switcher-data:/data
|
|
# Volume partage avec le Core + Watchtower : contient config.json avec
|
|
# les creds GHCR (ecrits par le Core a partir du token Patreon).
|
|
# Indispensable pour pull les images privees du canal beta.
|
|
- docker-config:/shared/docker
|
|
environment:
|
|
# Repertoire interne ou trouver docker-compose.yml et .env. Bind au
|
|
# volume ci-dessus (COMPOSE_PROJECT_DIR = repertoire d'install du host).
|
|
COMPOSE_DIR: /compose
|
|
# Nom de projet docker compose : fixe ici pour que le switcher cible
|
|
# le MEME stack que celui qui tourne (sinon il creerait un duplicate).
|
|
# Doit matcher le `name:` (en V2.x) ou le nom du dossier du host.
|
|
COMPOSE_PROJECT_NAME: ${COMPOSE_PROJECT_NAME:-loremind}
|
|
# Indique au CLI Docker du switcher ou trouver config.json (auth GHCR
|
|
# pour les images privees beta). Meme mecanisme que sur Watchtower.
|
|
DOCKER_CONFIG: /shared/docker
|
|
restart: unless-stopped
|
|
|
|
# Mises a jour automatiques des images core/brain/web.
|
|
# Active uniquement si COMPOSE_PROFILES=autoupdate (gere par l'installeur).
|
|
# Postgres et MinIO sont volontairement exclus (donnees persistantes,
|
|
# compatibilite de version a verifier manuellement).
|
|
watchtower:
|
|
# Fork maintenu de containrrr/watchtower (l'original est abandonne depuis
|
|
# ~2023 et son client Docker API est trop vieux pour les versions recentes
|
|
# de Docker Desktop -- erreur "client version 1.25 is too old").
|
|
# nickfedor/watchtower est un drop-in : memes variables d'environnement,
|
|
# meme API HTTP, juste l'image change.
|
|
image: nickfedor/watchtower:latest
|
|
container_name: loremind-watchtower
|
|
profiles: ["autoupdate"]
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
# Volume partage avec Core : credentials registry GHCR (canal beta).
|
|
# Watchtower lit le config.json depuis DOCKER_CONFIG.
|
|
- docker-config:/shared/docker
|
|
environment:
|
|
# Indique a Watchtower (et au CLI Docker embarque) ou trouver le
|
|
# config.json. Active automatiquement l'auth GHCR pour les images
|
|
# du canal beta des que Core a ecrit le fichier.
|
|
DOCKER_CONFIG: /shared/docker
|
|
WATCHTOWER_LABEL_ENABLE: "true"
|
|
WATCHTOWER_CLEANUP: "true"
|
|
WATCHTOWER_INCLUDE_RESTARTING: "true"
|
|
# MONITOR_ONLY=true => detecte sans appliquer (l'UI declenche manuellement).
|
|
# MONITOR_ONLY=false => applique automatiquement selon WATCHTOWER_SCHEDULE.
|
|
WATCHTOWER_MONITOR_ONLY: "${WATCHTOWER_MONITOR_ONLY:-false}"
|
|
WATCHTOWER_SCHEDULE: "${WATCHTOWER_SCHEDULE:-0 0 4 * * *}"
|
|
# API HTTP pour declenchement manuel via le bouton UI (Core -> Watchtower).
|
|
WATCHTOWER_HTTP_API_UPDATE: "true"
|
|
WATCHTOWER_HTTP_API_PERIODIC_POLLS: "true"
|
|
WATCHTOWER_HTTP_API_TOKEN: "${WATCHTOWER_TOKEN:?set WATCHTOWER_TOKEN in .env (re-run installer)}"
|
|
WATCHTOWER_TIMEOUT: 60s
|
|
WATCHTOWER_NOTIFICATIONS_LEVEL: info
|
|
TZ: ${TZ:-Europe/Paris}
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
postgres-data:
|
|
minio-data:
|
|
brain-data:
|
|
ollama-data:
|
|
# Volume partage Core <-> Watchtower : config.json Docker pour
|
|
# l'authentification au registry prive GHCR (canal beta Patreon).
|
|
docker-config:
|
|
# Volume partage Core <-> Switcher : commande de bascule de canal + resultat.
|
|
switcher-data:
|