# Déploiement d'applications avec URLs dynamiques Ce guide explique comment déployer vos applications avec Woodpecker CI en générant automatiquement des URLs dynamiques basées sur le nom de l'application et la branche Git. ## Vue d'ensemble ### Architecture ``` ┌─────────────────┐ │ Woodpecker CI │ │ (Pipeline) │ └────────┬────────┘ │ │ 1. Build & Deploy ▼ ┌─────────────────┐ │ Docker Image │ │ mon-app:latest │ └────────┬────────┘ │ │ 2. Run Container ▼ ┌─────────────────┐ ┌──────────────┐ │ Container │──────▶│ Consul │ │ mon-app │ │ (Service │ │ Labels Consul │ │ Discovery) │ └────────┬────────┘ └──────────────┘ │ │ 3. Auto-register ▼ ┌─────────────────┐ ┌──────────────────┐ │ Registrator │──────▶│ Nginx Proxy │ │ (Auto-detect) │ │ Manager │ └─────────────────┘ │ (Reverse Proxy) │ └──────────────────┘ │ │ 4. Configure Proxy ▼ ┌──────────────────┐ │ https:// │ │ mon-app.syoul.fr│ └──────────────────┘ ``` ### Flux de déploiement 1. **Build** : Woodpecker CI construit l'image Docker de l'application 2. **Deploy** : Le pipeline `.woodpecker.yml` lance le conteneur avec les labels Consul 3. **Discovery** : Registrator détecte automatiquement le conteneur et l'enregistre dans Consul 4. **Proxy** : Nginx Proxy Manager configure automatiquement le reverse proxy 5. **URL** : L'application est accessible via une URL dynamique (ex: `mon-app.syoul.fr`) ## Prérequis ### 1. Infrastructure en place - ✅ Woodpecker CI configuré et fonctionnel - ✅ Consul déployé avec ACL activées - ✅ Registrator déployé et fonctionnel - ✅ Nginx Proxy Manager installé (optionnel mais recommandé) ### 2. Variables d'environnement Pour utiliser le déploiement avec Nginx Proxy Manager, configurez ces variables dans Woodpecker : | Variable | Description | Exemple | |----------|-------------|---------| | `DOCKER_NETWORK` | Réseau Docker partagé | `gitgit_syoul_fr_gitea_net` | | `NPM_API_URL` | URL de l'API Nginx Proxy Manager | `http://npm-manager:81` | | `NPM_API_TOKEN` | Token d'API Nginx Proxy Manager | `votre-token-api` | | `DOMAIN_BASE` | Domaine de base pour les URLs | `syoul.fr` | | `CONSUL_TOKEN` | Token Consul (optionnel) | `votre-token-consul` | ### 3. Obtenir le token Nginx Proxy Manager 1. Connectez-vous à Nginx Proxy Manager 2. Allez dans **Account** > **API Tokens** 3. Créez un nouveau token avec les permissions nécessaires 4. Copiez le token et ajoutez-le dans les secrets Woodpecker ## Configuration du pipeline Woodpecker ### Approche recommandée : Tout dans `.woodpecker.yml` Toute la logique de déploiement est intégrée directement dans le fichier `.woodpecker.yml` de votre projet. Cela permet d'avoir tout au même endroit et de voir exactement ce qui se passe lors du déploiement. ### Avantages de cette approche - ✅ **Tout au même endroit** : La configuration est visible directement dans le pipeline - ✅ **Pas de dépendances externes** : Pas besoin de copier des scripts - ✅ **Facile à comprendre** : Tout est explicite dans le fichier YAML - ✅ **Personnalisable** : Facile d'adapter pour chaque projet ## Configuration Woodpecker CI ### Pipeline complet avec déploiement inline Créez un fichier `.woodpecker.yml` à la racine de votre projet : ```yaml pipeline: # Étape de build build: image: docker:24-dind privileged: true environment: - DOCKER_HOST=tcp://docker:2375 commands: - docker build -t ${CI_REPO_NAME}:${CI_COMMIT_SHA} . - docker tag ${CI_REPO_NAME}:${CI_COMMIT_SHA} ${CI_REPO_NAME}:latest # Déploiement sur la branche main deploy: image: docker:24-dind privileged: true environment: - APP_NAME=${CI_REPO_NAME} - APP_PORT=3000 # Adaptez selon votre application - DOCKER_NETWORK=${DOCKER_NETWORK:-gitgit_syoul_fr_gitea_net} - DOMAIN_BASE=${DOMAIN_BASE:-syoul.fr} - NPM_API_URL=${NPM_API_URL} # Secret Woodpecker - NPM_API_TOKEN=${NPM_API_TOKEN} # Secret Woodpecker commands: # Installer les dépendances - apk add --no-cache curl jq # Nettoyer le nom de l'application - APP_NAME_CLEAN=$(echo "${APP_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') # Générer l'URL dynamique - | if [ "$CI_COMMIT_BRANCH" = "main" ] || [ "$CI_COMMIT_BRANCH" = "master" ]; then SUBDOMAIN="${APP_NAME_CLEAN}" else BRANCH_CLEAN=$(echo "${CI_COMMIT_BRANCH}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') SUBDOMAIN="${APP_NAME_CLEAN}-${BRANCH_CLEAN}" fi - APP_URL="${SUBDOMAIN}.${DOMAIN_BASE}" - echo "🚀 Déploiement sur https://${APP_URL}" # Vérifier le réseau Docker - docker network inspect "${DOCKER_NETWORK}" || docker network create "${DOCKER_NETWORK}" || true # Arrêter l'ancien conteneur - docker stop "${APP_NAME_CLEAN}" 2>/dev/null || true - docker rm "${APP_NAME_CLEAN}" 2>/dev/null || true # Lancer le nouveau conteneur avec labels Consul - | CONTAINER_ID=$(docker run -d \ --name "${APP_NAME_CLEAN}" \ --network "${DOCKER_NETWORK}" \ --restart unless-stopped \ --label "SERVICE_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_TAGS=app,web,${CI_COMMIT_BRANCH}" \ --label "SERVICE_${APP_PORT}_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_${APP_PORT}_CHECK_HTTP=/" \ --label "SERVICE_${APP_PORT}_CHECK_INTERVAL=15s" \ -p "${APP_PORT}" \ "${APP_NAME_CLEAN}:latest") - sleep 3 - APP_CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${APP_NAME_CLEAN}") # Configurer Nginx Proxy Manager - | if [ -n "${NPM_API_URL}" ] && [ -n "${NPM_API_TOKEN}" ]; then 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 echo "✅ Proxy mis à jour" else 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}" > /dev/null echo "✅ Proxy créé" fi fi - echo "✅ Application déployée: https://${APP_URL}" when: branch: main status: success ``` ### Pipeline avancé avec tests et déploiement staging Pour un exemple complet avec tests et déploiement sur plusieurs branches, consultez le fichier `scripts/.woodpecker.yml.example` dans le dépôt infrastructure. ## Exemples par type d'application ### Application Node.js ```yaml pipeline: build: image: node:20-alpine commands: - npm ci - npm run build - docker build -t ${CI_REPO_NAME}:${CI_COMMIT_SHA} . - docker tag ${CI_REPO_NAME}:${CI_COMMIT_SHA} ${CI_REPO_NAME}:latest deploy: image: docker:24-dind privileged: true environment: - APP_NAME=${CI_REPO_NAME} - APP_PORT=3000 - DOCKER_NETWORK=${DOCKER_NETWORK:-gitgit_syoul_fr_gitea_net} - DOMAIN_BASE=${DOMAIN_BASE:-syoul.fr} - NPM_API_URL=${NPM_API_URL} - NPM_API_TOKEN=${NPM_API_TOKEN} commands: - apk add --no-cache curl jq - APP_NAME_CLEAN=$(echo "${APP_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') - | if [ "$CI_COMMIT_BRANCH" = "main" ]; then SUBDOMAIN="${APP_NAME_CLEAN}" else BRANCH_CLEAN=$(echo "${CI_COMMIT_BRANCH}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') SUBDOMAIN="${APP_NAME_CLEAN}-${BRANCH_CLEAN}" fi - APP_URL="${SUBDOMAIN}.${DOMAIN_BASE}" - docker network inspect "${DOCKER_NETWORK}" || docker network create "${DOCKER_NETWORK}" || true - docker stop "${APP_NAME_CLEAN}" 2>/dev/null || true - docker rm "${APP_NAME_CLEAN}" 2>/dev/null || true - | docker run -d \ --name "${APP_NAME_CLEAN}" \ --network "${DOCKER_NETWORK}" \ --restart unless-stopped \ --label "SERVICE_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_TAGS=app,web" \ --label "SERVICE_3000_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_3000_CHECK_HTTP=/" \ --label "SERVICE_3000_CHECK_INTERVAL=15s" \ -p 3000 \ "${APP_NAME_CLEAN}:latest" - sleep 3 - APP_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${APP_NAME_CLEAN}") # Configuration NPM (voir exemple complet ci-dessus) - echo "✅ Déployé sur https://${APP_URL}" ``` **Dockerfile exemple** : ```dockerfile FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . RUN npm run build EXPOSE 3000 CMD ["npm", "start"] ``` ### Application Python (Flask/FastAPI) ```yaml pipeline: build: image: python:3.11-alpine commands: - pip install -r requirements.txt - docker build -t ${CI_REPO_NAME}:${CI_COMMIT_SHA} . - docker tag ${CI_REPO_NAME}:${CI_COMMIT_SHA} ${CI_REPO_NAME}:latest deploy: image: docker:24-dind privileged: true environment: - APP_NAME=${CI_REPO_NAME} - APP_PORT=8000 - DOCKER_NETWORK=${DOCKER_NETWORK:-gitgit_syoul_fr_gitea_net} - DOMAIN_BASE=${DOMAIN_BASE:-syoul.fr} - NPM_API_URL=${NPM_API_URL} - NPM_API_TOKEN=${NPM_API_TOKEN} commands: - apk add --no-cache curl jq - APP_NAME_CLEAN=$(echo "${APP_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') - | if [ "$CI_COMMIT_BRANCH" = "main" ]; then SUBDOMAIN="${APP_NAME_CLEAN}" else BRANCH_CLEAN=$(echo "${CI_COMMIT_BRANCH}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') SUBDOMAIN="${APP_NAME_CLEAN}-${BRANCH_CLEAN}" fi - APP_URL="${SUBDOMAIN}.${DOMAIN_BASE}" - docker network inspect "${DOCKER_NETWORK}" || docker network create "${DOCKER_NETWORK}" || true - docker stop "${APP_NAME_CLEAN}" 2>/dev/null || true - docker rm "${APP_NAME_CLEAN}" 2>/dev/null || true - | docker run -d \ --name "${APP_NAME_CLEAN}" \ --network "${DOCKER_NETWORK}" \ --restart unless-stopped \ --label "SERVICE_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_TAGS=app,web" \ --label "SERVICE_8000_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_8000_CHECK_HTTP=/" \ --label "SERVICE_8000_CHECK_INTERVAL=15s" \ -p 8000 \ "${APP_NAME_CLEAN}:latest" - sleep 3 - APP_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${APP_NAME_CLEAN}") # Configuration NPM (voir exemple complet ci-dessus) - echo "✅ Déployé sur https://${APP_URL}" ``` **Dockerfile exemple** : ```dockerfile FROM python:3.11-alpine WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8000 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] ``` ### Application Go ```yaml pipeline: build: image: golang:1.21-alpine commands: - CGO_ENABLED=0 GOOS=linux go build -o app . - docker build -t ${CI_REPO_NAME}:${CI_COMMIT_SHA} . - docker tag ${CI_REPO_NAME}:${CI_COMMIT_SHA} ${CI_REPO_NAME}:latest deploy: image: docker:24-dind privileged: true environment: - APP_NAME=${CI_REPO_NAME} - APP_PORT=8080 - DOCKER_NETWORK=${DOCKER_NETWORK:-gitgit_syoul_fr_gitea_net} - DOMAIN_BASE=${DOMAIN_BASE:-syoul.fr} - NPM_API_URL=${NPM_API_URL} - NPM_API_TOKEN=${NPM_API_TOKEN} commands: - apk add --no-cache curl jq - APP_NAME_CLEAN=$(echo "${APP_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') - | if [ "$CI_COMMIT_BRANCH" = "main" ]; then SUBDOMAIN="${APP_NAME_CLEAN}" else BRANCH_CLEAN=$(echo "${CI_COMMIT_BRANCH}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') SUBDOMAIN="${APP_NAME_CLEAN}-${BRANCH_CLEAN}" fi - APP_URL="${SUBDOMAIN}.${DOMAIN_BASE}" - docker network inspect "${DOCKER_NETWORK}" || docker network create "${DOCKER_NETWORK}" || true - docker stop "${APP_NAME_CLEAN}" 2>/dev/null || true - docker rm "${APP_NAME_CLEAN}" 2>/dev/null || true - | docker run -d \ --name "${APP_NAME_CLEAN}" \ --network "${DOCKER_NETWORK}" \ --restart unless-stopped \ --label "SERVICE_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_TAGS=app,web" \ --label "SERVICE_8080_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_8080_CHECK_HTTP=/" \ --label "SERVICE_8080_CHECK_INTERVAL=15s" \ -p 8080 \ "${APP_NAME_CLEAN}:latest" - sleep 3 - APP_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${APP_NAME_CLEAN}") # Configuration NPM (voir exemple complet ci-dessus) - echo "✅ Déployé sur https://${APP_URL}" ``` **Dockerfile exemple** : ```dockerfile FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY app . EXPOSE 8080 CMD ["./app"] ``` ## Génération d'URLs dynamiques ### Règles de génération Le script génère les URLs selon ces règles : 1. **Branche main/master** : `{app-name}.{domain-base}` - Exemple: `mon-app.syoul.fr` 2. **Autres branches** : `{app-name}-{branch-name}.{domain-base}` - Exemple: `mon-app-feature-ui.syoul.fr` 3. **Nettoyage automatique** : - Conversion en minuscules - Remplacement des caractères spéciaux par des tirets - Suppression des caractères invalides ### Exemples | Application | Branche | URL générée | |-------------|---------|-------------| | `mon-app` | `main` | `mon-app.syoul.fr` | | `mon-app` | `develop` | `mon-app-develop.syoul.fr` | | `mon-app` | `feature/new-ui` | `mon-app-feature-new-ui.syoul.fr` | | `MyApp` | `main` | `myapp.syoul.fr` | | `app_name` | `main` | `app-name.syoul.fr` | ## Découverte de services avec Consul Une fois déployée, votre application est automatiquement enregistrée dans Consul grâce aux labels Docker. ### Lister les applications déployées ```bash export CONSUL_TOKEN="votre-token" curl -H "X-Consul-Token: $CONSUL_TOKEN" \ http://localhost:8500/v1/catalog/services | jq 'keys[] | select(. | contains("app"))' ``` ### Obtenir les détails d'une application ```bash curl -H "X-Consul-Token: $CONSUL_TOKEN" \ http://localhost:8500/v1/catalog/service/mon-app | jq ``` ### Vérifier la santé d'une application ```bash curl -H "X-Consul-Token: $CONSUL_TOKEN" \ http://localhost:8500/v1/health/service/mon-app | jq ``` ### Résolution DNS via Consul Si Consul DNS est configuré, vous pouvez résoudre les services : ```bash dig @localhost -p 8600 mon-app.service.consul ``` ## Configuration Nginx Proxy Manager ### Configuration automatique Le script configure automatiquement Nginx Proxy Manager si les variables `NPM_API_URL` et `NPM_API_TOKEN` sont définies. ### Configuration manuelle Si vous préférez configurer manuellement : 1. Connectez-vous à Nginx Proxy Manager 2. Allez dans **Hosts** > **Proxy Hosts** 3. Cliquez sur **Add Proxy Host** 4. Configurez : - **Domain Names** : `mon-app.syoul.fr` - **Forward Hostname/IP** : IP du conteneur (récupérée via `docker inspect`) - **Forward Port** : Port de l'application - **SSL** : Activer SSL et Let's Encrypt - **Block Common Exploits** : Activé - **Websockets Support** : Activé si nécessaire ### Récupérer l'IP du conteneur ```bash docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mon-app ``` ## Gestion des secrets ### Secrets Woodpecker Ajoutez les secrets dans Woodpecker : 1. Allez dans **Settings** > **Secrets** 2. Ajoutez : - `NPM_API_URL` : URL de l'API Nginx Proxy Manager - `NPM_API_TOKEN` : Token d'API - `DOMAIN_BASE` : Domaine de base - `CONSUL_TOKEN` : Token Consul (optionnel) ### Variables d'environnement par projet Vous pouvez aussi définir des variables spécifiques à chaque projet dans `.woodpecker.yml` : ```yaml pipeline: deploy: environment: - APP_PORT=3000 # Port spécifique au projet - DOMAIN_BASE=syoul.fr ``` ## Bonnes pratiques ### 1. Health checks Assurez-vous que votre application expose un endpoint de health check : ```yaml # Dans votre Dockerfile ou docker-compose.yml HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:${APP_PORT}/health || exit 1 ``` ### 2. Variables d'environnement Utilisez des variables d'environnement pour la configuration : ```yaml # Dans votre Dockerfile ENV APP_PORT=3000 ENV NODE_ENV=production ``` ### 3. Logs Configurez la gestion des logs : ```yaml # Dans docker-compose.yml ou via labels labels: - "logging=json-file" - "logging.max-size=10m" - "logging.max-file=3" ``` ### 4. Ressources Limitez les ressources des conteneurs : ```bash docker run -d \ --memory="512m" \ --cpus="0.5" \ --name mon-app \ mon-app:latest ``` ### 5. Rollback Pour faire un rollback, utilisez une image précédente : ```bash docker tag mon-app:previous-sha mon-app:latest # Relancer le pipeline Woodpecker ou exécuter manuellement les commandes de déploiement ``` ## Dépannage ### Le conteneur ne démarre pas ```bash # Vérifier les logs docker logs mon-app # Vérifier l'état du conteneur docker ps -a | grep mon-app ``` ### L'URL n'est pas accessible 1. Vérifier que le conteneur est en cours d'exécution : ```bash docker ps | grep mon-app ``` 2. Vérifier que le proxy est configuré dans Nginx Proxy Manager 3. Vérifier les DNS : ```bash dig mon-app.syoul.fr ``` ### Le service n'apparaît pas dans Consul 1. Vérifier que Registrator est en cours d'exécution : ```bash docker ps | grep registrator ``` 2. Vérifier les logs de Registrator : ```bash docker logs registrator | grep mon-app ``` 3. Vérifier les labels du conteneur : ```bash docker inspect mon-app | grep -A 10 Labels ``` ### Erreur d'API Nginx Proxy Manager 1. Vérifier que le token est valide 2. Vérifier que l'URL de l'API est correcte 3. Vérifier les permissions du token ## Exemples complets ### Projet complet Node.js **Structure** : ``` mon-app/ ├── .woodpecker.yml ├── Dockerfile └── package.json ``` **.woodpecker.yml** : ```yaml pipeline: test: image: node:20-alpine commands: - npm ci - npm test build: image: docker:24-dind privileged: true environment: - DOCKER_HOST=tcp://docker:2375 commands: - docker build -t ${CI_REPO_NAME}:${CI_COMMIT_SHA} . - docker tag ${CI_REPO_NAME}:${CI_COMMIT_SHA} ${CI_REPO_NAME}:latest deploy: image: docker:24-dind privileged: true environment: - APP_NAME=${CI_REPO_NAME} - APP_PORT=3000 - DOCKER_NETWORK=${DOCKER_NETWORK:-gitgit_syoul_fr_gitea_net} - DOMAIN_BASE=${DOMAIN_BASE:-syoul.fr} - NPM_API_URL=${NPM_API_URL} - NPM_API_TOKEN=${NPM_API_TOKEN} commands: - apk add --no-cache curl jq - APP_NAME_CLEAN=$(echo "${APP_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') - | if [ "$CI_COMMIT_BRANCH" = "main" ]; then SUBDOMAIN="${APP_NAME_CLEAN}" else BRANCH_CLEAN=$(echo "${CI_COMMIT_BRANCH}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g') SUBDOMAIN="${APP_NAME_CLEAN}-${BRANCH_CLEAN}" fi - APP_URL="${SUBDOMAIN}.${DOMAIN_BASE}" - docker network inspect "${DOCKER_NETWORK}" || docker network create "${DOCKER_NETWORK}" || true - docker stop "${APP_NAME_CLEAN}" 2>/dev/null || true - docker rm "${APP_NAME_CLEAN}" 2>/dev/null || true - | CONTAINER_ID=$(docker run -d \ --name "${APP_NAME_CLEAN}" \ --network "${DOCKER_NETWORK}" \ --restart unless-stopped \ --label "SERVICE_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_TAGS=app,web" \ --label "SERVICE_3000_NAME=${APP_NAME_CLEAN}" \ --label "SERVICE_3000_CHECK_HTTP=/" \ --label "SERVICE_3000_CHECK_INTERVAL=15s" \ -p 3000 \ "${APP_NAME_CLEAN}:latest") - sleep 3 - APP_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${APP_NAME_CLEAN}") - | if [ -n "${NPM_API_URL}" ] && [ -n "${NPM_API_TOKEN}" ]; then 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 echo "✅ Proxy mis à jour" else 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}" > /dev/null echo "✅ Proxy créé" fi fi - echo "✅ Application déployée: https://${APP_URL}" ``` **Dockerfile** : ```dockerfile FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . RUN npm run build EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=3s CMD node healthcheck.js CMD ["npm", "start"] ``` ## Conclusion Avec ce système, vous pouvez : - ✅ Déployer automatiquement vos applications avec Woodpecker CI - ✅ Générer des URLs dynamiques basées sur le nom et la branche - ✅ Découvrir automatiquement les services via Consul - ✅ Configurer automatiquement les reverse proxies - ✅ Surveiller la santé des applications Pour plus d'informations, consultez : - [Configuration Woodpecker](04-configuration-woodpecker.md) - [Configuration Consul](06-configuration-consul.md) - [Configuration Registrator](07-configuration-registrator.md)