From 0050ace888e8ad483cb2fea5da45506943166595 Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Mon, 22 Jun 2026 20:30:22 -0400 Subject: [PATCH] Update deploy doc to use docker-registry.dev.home:5000 + production compose --- docker-compose.production.yml | 87 +++++++++++ docs/DEPLOYMENT.md | 262 +++++----------------------------- 2 files changed, 125 insertions(+), 224 deletions(-) create mode 100644 docker-compose.production.yml diff --git a/docker-compose.production.yml b/docker-compose.production.yml new file mode 100644 index 0000000..05dd0e9 --- /dev/null +++ b/docker-compose.production.yml @@ -0,0 +1,87 @@ +# ═══════════════════════════════════════════════════════════════ +# Imago — Docker Compose Production +# ═══════════════════════════════════════════════════════════════ +# Utilise l'image depuis le registry local (pas de build). +# Déploiement : copier ce fichier + .env.production sur le serveur. +# +# Usage : +# docker compose -f docker-compose.production.yml up -d +# docker compose -f docker-compose.production.yml pull # mise à jour +# ═══════════════════════════════════════════════════════════════ + +services: + # ── API Backend ──────────────────────────────────────────── + backend: + image: docker-registry.dev.home:5000/imago-backend:latest + ports: + - "8000:8000" + env_file: .env.production + volumes: + - uploads:/app/data/uploads + - thumbnails:/app/data/thumbnails + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + restart: unless-stopped + + # ── Worker ARQ (pipeline AI) ─────────────────────────────── + worker: + image: docker-registry.dev.home:5000/imago-backend:latest + command: python worker.py + env_file: .env.production + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + restart: unless-stopped + + # ── PostgreSQL ───────────────────────────────────────────── + db: + image: postgres:16-alpine + environment: + POSTGRES_USER: imago + POSTGRES_DB: imago + env_file: .env.production + volumes: + - pgdata:/var/lib/postgresql/data + - ./backups:/backups + healthcheck: + test: ["CMD-SHELL", "pg_isready -U imago -d imago"] + interval: 5s + timeout: 5s + retries: 5 + restart: unless-stopped + + # ── Redis ────────────────────────────────────────────────── + redis: + image: redis:7-alpine + command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru + volumes: + - redisdata:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 3 + restart: unless-stopped + + # ── MinIO (stockage S3) ──────────────────────────────────── + minio: + image: minio/minio + command: server /data --console-address ":9001" + env_file: .env.production + environment: + MINIO_ROOT_USER: minioadmin + volumes: + - miniodata:/data + restart: unless-stopped + +volumes: + pgdata: + redisdata: + miniodata: + uploads: + thumbnails: diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index 68031f7..658e68e 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -1,46 +1,28 @@ # Guide de déploiement — Imago sur serveur Docker -> Cible : serveur Docker distant (VM Proxmox, VPS, ou bare metal) +> Cible : serveur Docker du lab (dev.lab.home / Proxmox) +> Registry : `docker-registry.dev.home:5000` > Prérequis : Docker 24+, Docker Compose v2, accès SSH --- -## Étape 1 — Préparer le registry d'images +## Étape 1 — Builder et pousser l'image vers le registry -Choisir UNE des options : +Depuis le poste de développement (Windows + WSL Debian) : -### Option A : Gitea Container Registry (recommandé si Gitea dispo) -```bash -# Builder et tagger l'image -cd C:\dev\git\python\imago -docker build -t gitea.dracodev.net/projets/imago-backend:latest . -docker build -t gitea.dracodev.net/projets/imago-admin:latest ./imago-admin +```powershell +cd C:\dev\git\python\imago\docker -# Se connecter au registry Gitea -docker login gitea.dracodev.net -u bruno +# Builder l'image +.\build-img.ps1 -# Pusher -docker push gitea.dracodev.net/projets/imago-backend:latest -docker push gitea.dracodev.net/projets/imago-admin:latest +# Pousser vers le registry (version semver auto-incrémentée) +.\deploy-img.ps1 ``` -### Option B : Docker Hub -```bash -docker build -t tonuser/imago-backend:latest . -docker build -t tonuser/imago-admin:latest ./imago-admin -docker push tonuser/imago-backend:latest -docker push tonuser/imago-admin:latest -``` - -### Option C : Registry local sur le serveur -```bash -# Sur le serveur cible -docker run -d -p 5000:5000 --name registry registry:2 - -# En local, builder et pusher -docker build -t localhost:5000/imago-backend:latest . -docker push localhost:5000/imago-backend:latest -``` +L'image est disponible à : +- `docker-registry.dev.home:5000/imago-backend:latest` +- `docker-registry.dev.home:5000/imago-backend:2.0.0` --- @@ -49,15 +31,15 @@ docker push localhost:5000/imago-backend:latest ```bash # Générer des secrets forts (à faire UNE SEULE fois) openssl rand -hex 32 # SECRET_KEY -openssl rand -hex 32 # ADMIN_API_KEY → note-la, c'est ta clé d'accès admin +openssl rand -hex 32 # ADMIN_API_KEY → note-la, c'est ta clé admin openssl rand -hex 32 # JWT_SECRET_KEY openssl rand -hex 32 # SIGNED_URL_SECRET -openssl rand -hex 16 # S3_SECRET_KEY openssl rand -hex 16 # MINIO_ROOT_PASSWORD openssl rand -hex 16 # POSTGRES_PASSWORD ``` -Créer le fichier `.env.production` : +Créer `.env.production` (remplacer les `<...>`) : + ```bash # ── Application ── APP_NAME=Imago @@ -68,7 +50,7 @@ SECRET_KEY= # ── Base de données ── DATABASE_URL=postgresql+asyncpg://imago:@db:5432/imago -# ── Stockage S3/MinIO ── +# ── Stockage MinIO ── STORAGE_BACKEND=s3 S3_BUCKET=imago S3_ENDPOINT_URL=http://minio:9000 @@ -85,7 +67,7 @@ JWT_ALGORITHM=HS256 # ── AI ── AI_ENABLED=true AI_PROVIDER=openrouter -OPENROUTER_API_KEY= +OPENROUTER_API_KEY= OPENROUTER_MODEL=qwen/qwen2.5-vl-72b-instruct AI_TAGS_MIN=5 AI_TAGS_MAX=10 @@ -98,179 +80,14 @@ OCR_ENABLED=true OCR_LANGUAGES=fra+eng # ── CORS ── -CORS_ORIGINS=["https://admin.ton-domaine.com"] +CORS_ORIGINS=["http://localhost:3000", "http://localhost:8000"] # ── Pipeline ── PIPELINE_TIMEOUT=300 PIPELINE_MAX_RETRIES=3 # ── Rate Limiting (Redis persistence) ── -RATE_LIMIT_STORAGE_URL=redis://redis:6379/1 -``` - ---- - -## Étape 3 — Préparer le docker-compose.production.yml - -```yaml -services: - traefik: - image: traefik:v3.0 - command: - - "--providers.docker=true" - - "--providers.docker.exposedbydefault=false" - - "--entrypoints.web.address=:80" - - "--entrypoints.websecure.address=:443" - - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true" - - "--certificatesresolvers.letsencrypt.acme.email=bruno.charest@gmail.com" - - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" - ports: - - "80:80" - - "443:443" - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - - traefik_certs:/letsencrypt - restart: unless-stopped - - backend: - image: gitea.dracodev.net/projets/imago-backend:latest - env_file: .env.production - labels: - - "traefik.enable=true" - - "traefik.http.routers.imago-api.rule=Host(`api.ton-domaine.com`)" - - "traefik.http.routers.imago-api.entrypoints=websecure" - - "traefik.http.routers.imago-api.tls.certresolver=letsencrypt" - depends_on: - db: - condition: service_healthy - redis: - condition: service_healthy - restart: unless-stopped - deploy: - resources: - limits: - memory: 1G - cpus: '2' - - worker: - image: gitea.dracodev.net/projets/imago-backend:latest - command: python worker.py - env_file: .env.production - depends_on: - db: - condition: service_healthy - redis: - condition: service_healthy - restart: unless-stopped - deploy: - resources: - limits: - memory: 512M - cpus: '1' - - admin: - image: nginx:alpine - ports: - - "127.0.0.1:3000:80" - volumes: - - ./admin-dist:/usr/share/nginx/html:ro - labels: - - "traefik.enable=true" - - "traefik.http.routers.imago-admin.rule=Host(`admin.ton-domaine.com`)" - - "traefik.http.routers.imago-admin.entrypoints=websecure" - - "traefik.http.routers.imago-admin.tls.certresolver=letsencrypt" - restart: unless-stopped - - db: - image: postgres:16-alpine - env_file: .env.production - environment: - POSTGRES_USER: imago - POSTGRES_DB: imago - volumes: - - pgdata:/var/lib/postgresql/data - - ./backups:/backups - healthcheck: - test: ["CMD-SHELL", "pg_isready -U imago -d imago"] - interval: 5s - timeout: 5s - retries: 5 - restart: unless-stopped - deploy: - resources: - limits: - memory: 512M - - redis: - image: redis:7-alpine - command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru - volumes: - - redisdata:/data - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 10s - timeout: 5s - retries: 3 - restart: unless-stopped - deploy: - resources: - limits: - memory: 256M - - minio: - image: minio/minio - command: server /data --console-address ":9001" - env_file: .env.production - volumes: - - miniodata:/data - restart: unless-stopped - deploy: - resources: - limits: - memory: 512M - -volumes: - pgdata: - redisdata: - miniodata: - traefik_certs: -``` - ---- - -## Étape 4 — Déployer sur le serveur - -```bash -# 1. Se connecter au serveur -ssh ton-serveur - -# 2. Créer le répertoire de l'application -mkdir -p /opt/imago && cd /opt/imago - -# 3. Copier les fichiers de configuration -# (depuis ton poste local) -scp docker-compose.production.yml ton-serveur:/opt/imago/ -scp .env.production ton-serveur:/opt/imago/ - -# 4. S'assurer que les volumes de backup existent -mkdir -p backups - -# 5. Démarrer la stack -docker compose -f docker-compose.production.yml up -d - -# 6. Vérifier les logs -docker compose -f docker-compose.production.yml logs -f backend - -# 7. Vérifier la santé -curl https://api.ton-domaine.com/health -``` - ---- - -## Étape 5 — Backup automatique (cron) - -Ajouter au crontab du serveur : -```cron +RATE_LIMIT_STORAGE_URL=redis://redis:***@#!/bin/bash # Backup PostgreSQL — tous les jours à 2h 0 2 * * * docker exec imago-db-1 pg_dump -U imago imago > /opt/imago/backups/imago_$(date +\%Y\%m\%d).sql @@ -280,29 +97,26 @@ Ajouter au crontab du serveur : --- -## Étape 6 — Vérifications post-déploiement - -- [ ] `https://api.ton-domaine.com/health` → `{"status":"healthy"}` -- [ ] `https://api.ton-domaine.com/health/detailed` → tous les checks OK -- [ ] `https://admin.ton-domaine.com` → page de login accessible -- [ ] Connexion admin avec `ADMIN_API_KEY` -- [ ] Upload d'une image test → pipeline OK -- [ ] WebSocket `/ws/pipeline/{id}` → événements reçus -- [ ] Métriques Prometheus `/metrics` → données présentes - ---- - -## Résumé des commandes rapides +## Étape 5 — Vérifications post-déploiement ```bash -# Builder les images (local) -docker build -t gitea.dracodev.net/projets/imago-backend:latest . -docker login gitea.dracodev.net -docker push gitea.dracodev.net/projets/imago-backend:latest +# Vérifier que tous les conteneurs tournent +docker compose -f /opt/imago/docker-compose.production.yml ps -# Déployer (serveur) -ssh serveur "cd /opt/imago && docker compose pull && docker compose up -d" +# Santé de l'API +curl http://localhost:8000/health -# Vérifier -curl https://api.ton-domaine.com/health +# Santé détaillée (tous les services) +curl http://localhost:8000/health/detailed + +# Accéder au panneau admin +curl http://localhost:3000 ``` + +Checklist : +- [ ] `http://localhost:8000/health` → `{"status":"healthy"}` +- [ ] `http://localhost:8000/health/detailed` → tous les checks OK +- [ ] `http://localhost:3000` → page de login accessible +- [ ] Connexion admin avec `ADMIN_API_KEY` +- [ ] Upload d'une image test → pipeline OK +- [ ] Métriques Prometheus `/metrics` → données présentes