#!/bin/bash # deploy.sh - Script de déploiement générique avec URLs dynamiques # Usage: ./deploy.sh [port] [branch] [domain-base] set -e # Couleurs pour les messages RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Fonction d'aide usage() { echo "Usage: $0 [port] [branch] [domain-base]" echo "" echo "Arguments:" echo " app-name : Nom de l'application (requis)" echo " port : Port de l'application (défaut: 8080)" echo " branch : Branche Git (défaut: main ou CI_COMMIT_BRANCH)" echo " domain-base : Domaine de base (défaut: syoul.fr)" echo "" echo "Variables d'environnement:" echo " DOCKER_NETWORK : Réseau Docker (défaut: gitgit_syoul_fr_gitea_net)" echo " NPM_API_URL : URL de l'API Nginx Proxy Manager" echo " NPM_API_TOKEN : Token d'API Nginx Proxy Manager" echo " CONSUL_TOKEN : Token Consul pour la découverte de services" echo "" exit 1 } # Vérifier les arguments if [ $# -lt 1 ]; then usage fi APP_NAME=${1} APP_PORT=${2:-8080} BRANCH=${3:-${CI_COMMIT_BRANCH:-main}} DOMAIN_BASE=${4:-${DOMAIN_BASE:-syoul.fr}} DOCKER_NETWORK=${DOCKER_NETWORK:-gitgit_syoul_fr_gitea_net} # Nettoyer le nom de l'application (minuscules, pas de caractères spéciaux) APP_NAME=$(echo "${APP_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') # Générer le sous-domaine basé sur la branche if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then SUBDOMAIN="${APP_NAME}" else # Pour les branches : app-name-branch-name (nettoyé) BRANCH_CLEAN=$(echo "${BRANCH}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') SUBDOMAIN="${APP_NAME}-${BRANCH_CLEAN}" fi APP_URL="${SUBDOMAIN}.${DOMAIN_BASE}" echo -e "${BLUE}🚀 Déploiement de ${APP_NAME}${NC}" echo -e " Port: ${APP_PORT}" echo -e " Branche: ${BRANCH}" echo -e " URL: https://${APP_URL}" # Vérifier que Docker est disponible if ! command -v docker &> /dev/null; then echo -e "${RED}❌ Docker n'est pas installé ou non accessible${NC}" exit 1 fi # Vérifier que le réseau Docker existe if ! docker network inspect "${DOCKER_NETWORK}" &> /dev/null; then echo -e "${YELLOW}⚠️ Le réseau ${DOCKER_NETWORK} n'existe pas, création...${NC}" docker network create "${DOCKER_NETWORK}" || true fi # Arrêter et supprimer l'ancien conteneur s'il existe echo -e "${BLUE}📦 Arrêt de l'ancien conteneur...${NC}" docker stop "${APP_NAME}" 2>/dev/null || true docker rm "${APP_NAME}" 2>/dev/null || true # Vérifier que l'image existe if ! docker image inspect "${APP_NAME}:latest" &> /dev/null; then echo -e "${YELLOW}⚠️ L'image ${APP_NAME}:latest n'existe pas${NC}" echo -e "${YELLOW} Assurez-vous d'avoir construit l'image avant de déployer${NC}" exit 1 fi # Lancer le nouveau conteneur avec labels Consul echo -e "${BLUE}🐳 Lancement du conteneur...${NC}" CONTAINER_ID=$(docker run -d \ --name "${APP_NAME}" \ --network "${DOCKER_NETWORK}" \ --restart unless-stopped \ --label "SERVICE_NAME=${APP_NAME}" \ --label "SERVICE_TAGS=app,web,${BRANCH}" \ --label "SERVICE_${APP_PORT}_NAME=${APP_NAME}" \ --label "SERVICE_${APP_PORT}_CHECK_HTTP=/" \ --label "SERVICE_${APP_PORT}_CHECK_INTERVAL=15s" \ -p "${APP_PORT}" \ "${APP_NAME}:latest") if [ -z "${CONTAINER_ID}" ]; then echo -e "${RED}❌ Échec du lancement du conteneur${NC}" exit 1 fi echo -e "${GREEN}✅ Conteneur lancé: ${CONTAINER_ID}${NC}" # Attendre que le conteneur soit prêt echo -e "${BLUE}⏳ Attente du démarrage du conteneur...${NC}" sleep 3 # Récupérer l'IP du conteneur APP_CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${APP_NAME}") if [ -z "${APP_CONTAINER_IP}" ]; then echo -e "${RED}❌ Impossible de récupérer l'IP du conteneur${NC}" exit 1 fi echo -e "${GREEN}📍 IP interne: ${APP_CONTAINER_IP}:${APP_PORT}${NC}" # Configurer Nginx Proxy Manager si les variables sont définies if [ -n "${NPM_API_URL}" ] && [ -n "${NPM_API_TOKEN}" ]; then echo -e "${BLUE}📝 Configuration du reverse proxy Nginx Proxy Manager...${NC}" # Vérifier que curl et jq sont disponibles if ! command -v curl &> /dev/null; then echo -e "${YELLOW}⚠️ curl n'est pas disponible, installation...${NC}" apk add --no-cache curl 2>/dev/null || apt-get update && apt-get install -y curl 2>/dev/null || true fi if ! command -v jq &> /dev/null; then echo -e "${YELLOW}⚠️ jq n'est pas disponible, installation...${NC}" apk add --no-cache jq 2>/dev/null || apt-get update && apt-get install -y jq 2>/dev/null || true fi # Vérifier si le proxy existe déjà EXISTING_PROXY=$(curl -s -H "Authorization: Bearer ${NPM_API_TOKEN}" \ "${NPM_API_URL}/api/nginx/proxy-hosts" 2>/dev/null | \ jq -r ".[] | select(.domain_names[] == \"${APP_URL}\") | .id" 2>/dev/null | head -1) PROXY_DATA=$(cat </dev/null) if echo "${RESPONSE}" | jq -e '.id' &> /dev/null; then echo -e "${GREEN}✅ Proxy mis à jour avec succès${NC}" else echo -e "${YELLOW}⚠️ Échec de la mise à jour du proxy: ${RESPONSE}${NC}" fi else # Créer un nouveau proxy echo -e "${BLUE} Création d'un nouveau proxy...${NC}" RESPONSE=$(curl -s -X POST "${NPM_API_URL}/api/nginx/proxy-hosts" \ -H "Authorization: Bearer ${NPM_API_TOKEN}" \ -H "Content-Type: application/json" \ -d "${PROXY_DATA}" 2>/dev/null) if echo "${RESPONSE}" | jq -e '.id' &> /dev/null; then echo -e "${GREEN}✅ Proxy créé avec succès${NC}" else echo -e "${YELLOW}⚠️ Échec de la création du proxy: ${RESPONSE}${NC}" echo -e "${YELLOW} Vous devrez configurer manuellement le proxy dans Nginx Proxy Manager${NC}" fi fi else echo -e "${YELLOW}⚠️ NPM_API_URL ou NPM_API_TOKEN non définis${NC}" echo -e "${YELLOW} Configuration manuelle du reverse proxy requise${NC}" echo -e "${YELLOW} Domaine: ${APP_URL} -> ${APP_CONTAINER_IP}:${APP_PORT}${NC}" fi # Vérifier l'enregistrement dans Consul (si disponible) if [ -n "${CONSUL_TOKEN}" ]; then echo -e "${BLUE}🔍 Vérification de l'enregistrement dans Consul...${NC}" sleep 2 # Attendre que Registrator enregistre le service CONSUL_SERVICE=$(curl -s -H "X-Consul-Token: ${CONSUL_TOKEN}" \ "http://localhost:8500/v1/catalog/service/${APP_NAME}" 2>/dev/null | \ jq -r '.[0].ServiceName' 2>/dev/null) if [ "${CONSUL_SERVICE}" = "${APP_NAME}" ]; then echo -e "${GREEN}✅ Service enregistré dans Consul${NC}" else echo -e "${YELLOW}⚠️ Service non encore visible dans Consul (peut prendre quelques secondes)${NC}" fi fi # Résumé du déploiement echo "" echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}" echo -e "${GREEN}✅ Déploiement terminé avec succès${NC}" echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}" echo -e "Application: ${APP_NAME}" echo -e "URL: https://${APP_URL}" echo -e "IP interne: ${APP_CONTAINER_IP}:${APP_PORT}" echo -e "Conteneur: ${CONTAINER_ID}" echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}"