refactor: structure docker-compose/ + scripts deploy.sh et setup.sh
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# Imago — Script de déploiement automatisé
|
||||
# =============================================================================
|
||||
# Usage :
|
||||
# ./scripts/deploy.sh # Premier déploiement
|
||||
# ./scripts/deploy.sh --update # Mise à jour (pull + recréation)
|
||||
# ./scripts/deploy.sh --status # Afficher l'état des conteneurs
|
||||
# ./scripts/deploy.sh --logs # Logs en temps réel
|
||||
#
|
||||
# Prérequis : Docker + Docker Compose installés (voir scripts/setup.sh)
|
||||
# =============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── Couleurs ──────────────────────────────────────────────────
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'; NC='\033[0m'
|
||||
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
||||
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
err() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
||||
|
||||
# ── Configuration ─────────────────────────────────────────────
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
COMPOSE_FILE="${PROJECT_DIR}/docker-compose/docker-compose.prod.yml"
|
||||
ENV_FILE="${PROJECT_DIR}/.env"
|
||||
ENV_EXAMPLE="${PROJECT_DIR}/docker-compose/.env.example"
|
||||
SERVICE_NAME="imago"
|
||||
|
||||
# ── Fonctions ─────────────────────────────────────────────────
|
||||
|
||||
check_prerequisites() {
|
||||
info "Vérification des prérequis..."
|
||||
|
||||
if ! command -v docker &>/dev/null; then
|
||||
err "Docker n'est pas installé. Lancez : scripts/setup.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker compose version &>/dev/null; then
|
||||
err "Docker Compose (plugin) n'est pas disponible."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker info &>/dev/null; then
|
||||
err "Docker ne tourne pas ou vous n'avez pas les droits."
|
||||
err "Vérifiez : sudo systemctl start docker && sudo usermod -aG docker $USER"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ok "Docker $(docker --version | awk '{print $3}' | tr -d ',') — Docker Compose disponible"
|
||||
}
|
||||
|
||||
setup_env() {
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
ok "Fichier .env existant"
|
||||
return
|
||||
fi
|
||||
|
||||
warn "Fichier .env absent — création depuis le template..."
|
||||
if [[ ! -f "$ENV_EXAMPLE" ]]; then
|
||||
err "Template introuvable : $ENV_EXAMPLE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp "$ENV_EXAMPLE" "$ENV_FILE"
|
||||
warn "╔══════════════════════════════════════════════════════════╗"
|
||||
warn "║ Fichier .env créé. ÉDITEZ-LE avant de continuer : ║"
|
||||
warn "║ nano ${ENV_FILE} ║"
|
||||
warn "║ ║"
|
||||
warn "║ Variables OBLIGATOIRES à renseigner : ║"
|
||||
warn "║ SECRET_KEY — clé secrète aléatoire ║"
|
||||
warn "║ SIGNED_URL_SECRET — clé pour URLs signées ║"
|
||||
warn "║ OPENROUTER_API_KEY — clé API OpenRouter ║"
|
||||
warn "║ ADMIN_API_KEY — (optionnel) master key admin ║"
|
||||
warn "╚══════════════════════════════════════════════════════════╝"
|
||||
|
||||
echo ""
|
||||
read -rp "Avez-vous édité le fichier .env ? (o/N) " confirm
|
||||
if [[ ! "$confirm" =~ ^[oO]$ ]]; then
|
||||
err "Déploiement annulé. Éditez .env puis relancez."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
create_directories() {
|
||||
info "Création des répertoires..."
|
||||
|
||||
# Répertoire de backups
|
||||
local backup_dir="${BACKUP_DIR:-./backups}"
|
||||
if [[ ! -d "$PROJECT_DIR/$backup_dir" ]]; then
|
||||
mkdir -p "$PROJECT_DIR/$backup_dir"
|
||||
ok "Backups : $backup_dir"
|
||||
fi
|
||||
|
||||
# Répertoires NFS si configurés
|
||||
local upload_vol="${UPLOAD_VOLUME:-}"
|
||||
if [[ -n "$upload_vol" ]] && [[ ! "$upload_vol" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
||||
mkdir -p "$upload_vol" 2>/dev/null || warn "Impossible de créer $upload_vol (NFS ?)"
|
||||
fi
|
||||
}
|
||||
|
||||
pull_images() {
|
||||
info "Récupération des images Docker..."
|
||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" pull --quiet 2>&1 | tail -3
|
||||
ok "Images à jour"
|
||||
}
|
||||
|
||||
start_services() {
|
||||
info "Démarrage des services..."
|
||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --remove-orphans
|
||||
|
||||
info "Attente de la santé des services..."
|
||||
local max_wait=60
|
||||
local waited=0
|
||||
while [[ $waited -lt $max_wait ]]; do
|
||||
local backend_ok=$(docker compose -f "$COMPOSE_FILE" ps backend --format json 2>/dev/null | grep -c '"Health":"healthy"' || echo 0)
|
||||
if [[ "$backend_ok" -ge 1 ]]; then
|
||||
ok "Backend healthy après ${waited}s"
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
waited=$((waited + 3))
|
||||
echo -n "."
|
||||
done
|
||||
echo ""
|
||||
|
||||
if [[ $waited -ge $max_wait ]]; then
|
||||
warn "Le backend tarde à démarrer (>${max_wait}s). Vérifiez les logs :"
|
||||
warn " docker compose -f $COMPOSE_FILE logs backend"
|
||||
fi
|
||||
}
|
||||
|
||||
show_bootstrap_key() {
|
||||
echo ""
|
||||
info "Clé API bootstrap (admin) — si c'est un premier déploiement :"
|
||||
docker compose -f "$COMPOSE_FILE" logs backend 2>/dev/null | \
|
||||
grep "API_KEY:" | tail -1 | \
|
||||
sed 's/.*API_KEY: / /' | sed 's/".*//' || true
|
||||
}
|
||||
|
||||
show_status() {
|
||||
echo ""
|
||||
info "État des services :"
|
||||
docker compose -f "$COMPOSE_FILE" ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
|
||||
}
|
||||
|
||||
show_urls() {
|
||||
echo ""
|
||||
ok "═══ Imago est prêt ═══"
|
||||
local admin_port="${ADMIN_PORT:-3001}"
|
||||
local backend_port="${BACKEND_PORT:-8001}"
|
||||
echo " Admin UI : http://$(hostname -I 2>/dev/null | awk '{print $1}' || echo 'localhost'):${admin_port}"
|
||||
echo " API Docs : http://$(hostname -I 2>/dev/null | awk '{print $1}' || echo 'localhost'):${backend_port}/docs"
|
||||
echo " Health : http://$(hostname -I 2>/dev/null | awk '{print $1}' || echo 'localhost'):${backend_port}/health"
|
||||
}
|
||||
|
||||
restart_updated() {
|
||||
info "Mise à jour : pull + recréation des services modifiés..."
|
||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" pull --quiet
|
||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --remove-orphans
|
||||
ok "Services mis à jour"
|
||||
}
|
||||
|
||||
# ── Point d'entrée ───────────────────────────────────────────
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
case "${1:-}" in
|
||||
--update|-u)
|
||||
check_prerequisites
|
||||
pull_images
|
||||
restart_updated
|
||||
show_status
|
||||
show_urls
|
||||
;;
|
||||
--status|-s)
|
||||
show_status
|
||||
;;
|
||||
--logs|-l)
|
||||
docker compose -f "$COMPOSE_FILE" logs -f --tail=50
|
||||
;;
|
||||
--help|-h)
|
||||
echo "Usage: $0 [--update|--status|--logs|--help]"
|
||||
echo ""
|
||||
echo " (sans argument) Premier déploiement complet"
|
||||
echo " --update, -u Mise à jour des containers"
|
||||
echo " --status, -s Afficher l'état"
|
||||
echo " --logs, -l Logs en temps réel"
|
||||
echo " --help, -h Cette aide"
|
||||
;;
|
||||
*)
|
||||
check_prerequisites
|
||||
setup_env
|
||||
create_directories
|
||||
pull_images
|
||||
start_services
|
||||
show_bootstrap_key
|
||||
show_status
|
||||
show_urls
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# Imago — Script de préparation du serveur (one-time setup)
|
||||
# =============================================================================
|
||||
# Usage :
|
||||
# sudo ./scripts/setup.sh
|
||||
#
|
||||
# Ce script :
|
||||
# 1. Installe Docker + Docker Compose si absents
|
||||
# 2. Configure les droits utilisateur (groupe docker)
|
||||
# 3. Vérifie les prérequis système
|
||||
# 4. Crée les répertoires nécessaires
|
||||
# =============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'; NC='\033[0m'
|
||||
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
||||
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
err() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
||||
|
||||
# ── Vérification root ────────────────────────────────────────
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
err "Ce script doit être lancé en root : sudo ./scripts/setup.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Récupérer l'utilisateur réel (même si lancé via sudo)
|
||||
REAL_USER="${SUDO_USER:-$USER}"
|
||||
REAL_HOME=$(eval echo "~$REAL_USER")
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════════"
|
||||
echo " Imago — Préparation du serveur"
|
||||
echo " Utilisateur : $REAL_USER"
|
||||
echo "═══════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
# ── 1. Installer Docker ─────────────────────────────────────
|
||||
install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
ok "Docker déjà installé : $(docker --version)"
|
||||
return
|
||||
fi
|
||||
|
||||
info "Installation de Docker..."
|
||||
|
||||
if command -v apt-get &>/dev/null; then
|
||||
# Debian / Ubuntu
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq ca-certificates curl
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
|
||||
chmod a+r /etc/apt/keyrings/docker.asc
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" > /etc/apt/sources.list.d/docker.list
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
ok "Docker installé via apt"
|
||||
|
||||
elif command -v dnf &>/dev/null; then
|
||||
# Fedora / RHEL
|
||||
dnf -y install dnf-plugins-core
|
||||
dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
|
||||
dnf -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
ok "Docker installé via dnf"
|
||||
|
||||
else
|
||||
err "Distribution non supportée. Installez Docker manuellement :"
|
||||
err " https://docs.docker.com/engine/install/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
systemctl enable docker --now
|
||||
}
|
||||
|
||||
# ── 2. Ajouter l'utilisateur au groupe docker ───────────────
|
||||
configure_user() {
|
||||
if groups "$REAL_USER" | grep -q docker; then
|
||||
ok "Utilisateur $REAL_USER déjà dans le groupe docker"
|
||||
return
|
||||
fi
|
||||
|
||||
info "Ajout de $REAL_USER au groupe docker..."
|
||||
usermod -aG docker "$REAL_USER"
|
||||
ok "Utilisateur $REAL_USER ajouté au groupe docker"
|
||||
warn "╔══════════════════════════════════════════════════════════╗"
|
||||
warn "║ Déconnectez-vous puis reconnectez-vous pour que les ║"
|
||||
warn "║ changements de groupe prennent effet. ║"
|
||||
warn "║ Ou lancez : newgrp docker ║"
|
||||
warn "╚══════════════════════════════════════════════════════════╝"
|
||||
}
|
||||
|
||||
# ── 3. Vérifier le système ──────────────────────────────────
|
||||
check_system() {
|
||||
info "Vérification système..."
|
||||
|
||||
# Espace disque
|
||||
local disk_avail=$(df -BG /var/lib/docker 2>/dev/null | awk 'NR==2 {print $4}' | tr -d 'G' || df -BG / | awk 'NR==2 {print $4}' | tr -d 'G')
|
||||
if [[ ${disk_avail:-0} -lt 10 ]]; then
|
||||
warn "Espace disque faible : ${disk_avail}G disponibles. 10G+ recommandé."
|
||||
else
|
||||
ok "Espace disque : ${disk_avail}G disponibles"
|
||||
fi
|
||||
|
||||
# RAM
|
||||
local mem_total=$(free -m | awk '/^Mem:/{print $2}')
|
||||
if [[ ${mem_total:-0} -lt 2048 ]]; then
|
||||
warn "RAM faible : ${mem_total}MB. 2GB+ recommandé."
|
||||
else
|
||||
ok "RAM : ${mem_total}MB"
|
||||
fi
|
||||
|
||||
# Docker fonctionnel
|
||||
if docker info &>/dev/null; then
|
||||
ok "Docker opérationnel"
|
||||
else
|
||||
err "Docker ne répond pas. Vérifiez : systemctl start docker"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 4. Créer le répertoire de travail ────────────────────────
|
||||
create_workdir() {
|
||||
local workdir="${1:-/opt/imago}"
|
||||
if [[ -d "$workdir" ]]; then
|
||||
ok "Répertoire de travail existant : $workdir"
|
||||
return
|
||||
fi
|
||||
|
||||
info "Création du répertoire de travail : $workdir"
|
||||
mkdir -p "$workdir"
|
||||
chown "$REAL_USER:$REAL_USER" "$workdir"
|
||||
ok "Répertoire créé : $workdir"
|
||||
}
|
||||
|
||||
# ── Exécution ────────────────────────────────────────────────
|
||||
|
||||
install_docker
|
||||
configure_user
|
||||
check_system
|
||||
create_workdir "/opt/imago"
|
||||
|
||||
echo ""
|
||||
ok "═══ Serveur prêt pour Imago ═══"
|
||||
echo ""
|
||||
echo " Prochaines étapes :"
|
||||
echo " 1. Déconnectez/reconnectez-vous (groupe docker)"
|
||||
echo " 2. Clonez le dépôt :"
|
||||
echo " git clone <repo-url> /opt/imago"
|
||||
echo " 3. Déployez :"
|
||||
echo " cd /opt/imago && ./scripts/deploy.sh"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user