- Documentation complète pour Nginx Proxy Manager (docs/10-configuration-nginx-proxy-manager.md) - Script get-npm-token.sh pour générer automatiquement les tokens API - Exemple complet de .woodpecker.yml avec logique inline de déploiement - Documentation déploiement applications avec URLs dynamiques (docs/09-deploiement-applications.md) - Script deploy.sh comme alternative optionnelle - Mise à jour README avec références aux nouvelles documentations
24 KiB
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
- Build : Woodpecker CI construit l'image Docker de l'application
- Deploy : Le pipeline
.woodpecker.ymllance le conteneur avec les labels Consul - Discovery : Registrator détecte automatiquement le conteneur et l'enregistre dans Consul
- Proxy : Nginx Proxy Manager configure automatiquement le reverse proxy
- 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
- Connectez-vous à Nginx Proxy Manager
- Allez dans Account > API Tokens
- Créez un nouveau token avec les permissions nécessaires
- 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 :
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 <<EOF
{
"domain_names": ["${APP_URL}"],
"forward_scheme": "http",
"forward_host": "${APP_CONTAINER_IP}",
"forward_port": ${APP_PORT},
"ssl_forced": true,
"hsts_enabled": true,
"hsts_subdomains": true,
"block_exploits": true,
"caching_enabled": true,
"allow_websocket_upgrade": true
}
EOF
)
if [ -n "${EXISTING_PROXY}" ]; then
curl -s -X PUT "${NPM_API_URL}/api/nginx/proxy-hosts/${EXISTING_PROXY}" \
-H "Authorization: Bearer ${NPM_API_TOKEN}" \
-H "Content-Type: application/json" \
-d "${PROXY_DATA}" > /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
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 :
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)
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 :
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
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 :
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 :
-
Branche main/master :
{app-name}.{domain-base}- Exemple:
mon-app.syoul.fr
- Exemple:
-
Autres branches :
{app-name}-{branch-name}.{domain-base}- Exemple:
mon-app-feature-ui.syoul.fr
- Exemple:
-
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
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
curl -H "X-Consul-Token: $CONSUL_TOKEN" \
http://localhost:8500/v1/catalog/service/mon-app | jq
Vérifier la santé d'une application
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 :
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 :
- Connectez-vous à Nginx Proxy Manager
- Allez dans Hosts > Proxy Hosts
- Cliquez sur Add Proxy Host
- 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
- Domain Names :
Récupérer l'IP du conteneur
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mon-app
Gestion des secrets
Secrets Woodpecker
Ajoutez les secrets dans Woodpecker :
- Allez dans Settings > Secrets
- Ajoutez :
NPM_API_URL: URL de l'API Nginx Proxy ManagerNPM_API_TOKEN: Token d'APIDOMAIN_BASE: Domaine de baseCONSUL_TOKEN: Token Consul (optionnel)
Variables d'environnement par projet
Vous pouvez aussi définir des variables spécifiques à chaque projet dans .woodpecker.yml :
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 :
# 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 :
# Dans votre Dockerfile
ENV APP_PORT=3000
ENV NODE_ENV=production
3. Logs
Configurez la gestion des logs :
# 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 :
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 :
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
# 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
-
Vérifier que le conteneur est en cours d'exécution :
docker ps | grep mon-app -
Vérifier que le proxy est configuré dans Nginx Proxy Manager
-
Vérifier les DNS :
dig mon-app.syoul.fr
Le service n'apparaît pas dans Consul
-
Vérifier que Registrator est en cours d'exécution :
docker ps | grep registrator -
Vérifier les logs de Registrator :
docker logs registrator | grep mon-app -
Vérifier les labels du conteneur :
docker inspect mon-app | grep -A 10 Labels
Erreur d'API Nginx Proxy Manager
- Vérifier que le token est valide
- Vérifier que l'URL de l'API est correcte
- Vérifier les permissions du token
Exemples complets
Projet complet Node.js
Structure :
mon-app/
├── .woodpecker.yml
├── Dockerfile
└── package.json
.woodpecker.yml :
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 <<EOF
{
"domain_names": ["${APP_URL}"],
"forward_scheme": "http",
"forward_host": "${APP_IP}",
"forward_port": 3000,
"ssl_forced": true,
"hsts_enabled": true,
"hsts_subdomains": true,
"block_exploits": true,
"caching_enabled": true,
"allow_websocket_upgrade": true
}
EOF
)
if [ -n "${EXISTING_PROXY}" ]; then
curl -s -X PUT "${NPM_API_URL}/api/nginx/proxy-hosts/${EXISTING_PROXY}" \
-H "Authorization: Bearer ${NPM_API_TOKEN}" \
-H "Content-Type: application/json" \
-d "${PROXY_DATA}" > /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 :
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 :