Introduction
Azure App Service est la plateforme PaaS leader pour héberger des applications web, mobiles et API sans gérer l'infrastructure sous-jacente. En 2026, avec l'essor de l'IA et des workloads hybrides, maîtriser App Service avancé signifie implémenter des déploiements zero-downtime via slots, autoscaling intelligent avec KEDA, et CI/CD natif GitHub. Ce tutoriel avancé guide un développeur senior à travers la création d'une app Node.js Express, son déploiement via Azure CLI et Bicep, configuration de slots pour blue-green deployments, et scaling basé sur métriques custom.
Pourquoi c'est crucial ? Les apps modernes subissent des pics imprévisibles ; App Service excelle avec son intégration seamless à Azure Monitor, Application Insights et Virtual Network. Vous économiserez des heures sur les ops en automatisant tout. À la fin, votre app sera production-ready, scalable à 1000+ instances, avec monitoring proactif. Prêt à passer pro ? (128 mots)
Prérequis
- Compte Azure gratuit ou payant (crédit suffisant pour App Service Plan Premium)
- Azure CLI 2.65+ installé
- Node.js 20+ et npm
- GitHub account avec repo privé
- VS Code avec extensions Azure App Service et Bicep
- Connaissances avancées en TypeScript, DevOps et ARM/Bicep
Créer l'application Node.js de base
import express, { Request, Response, NextFunction } from 'express';
import helmet from 'helmet';
import cors from 'cors';
const app = express();
const PORT = process.env.PORT || 8080;
app.use(helmet());
app.use(cors());
app.use(express.json());
app.get('/health', (req: Request, res: Response) => {
res.status(200).json({ status: 'healthy', timestamp: new Date().toISOString() });
});
app.get('/api/metrics', (req: Request, res: Response) => {
// Simulate CPU-intensive metric for scaling demo
const load = Math.random() * 100;
res.json({ cpuLoad: load, requests: process.env.REQUEST_COUNT || '0' });
});
app.post('/api/increment', (req: Request, res: Response) => {
const count = (parseInt(process.env.REQUEST_COUNT || '0') + 1).toString();
process.env.REQUEST_COUNT = count;
res.json({ incremented: count });
});
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
console.error(err.stack);
res.status(500).json({ error: 'Internal Server Error' });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});Ce serveur Express TypeScript inclut sécurité (Helmet, CORS), health check pour liveness/readiness probes, et endpoints pour simuler charge CPU/requests. Les variables d'env comme REQUEST_COUNT persistent via App Settings. Piège : Toujours typer Request/Response pour éviter erreurs runtime ; testez localement avec npx ts-node src/server.ts.
Générer package.json et tsconfig.json
{
"name": "azure-app-service-demo",
"version": "1.0.0",
"main": "dist/server.js",
"scripts": {
"build": "tsc",
"start": "node dist/server.js",
"dev": "ts-node src/server.ts"
},
"dependencies": {
"express": "^4.19.2",
"helmet": "^7.1.0",
"cors": "^2.8.5"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.11.19",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
}Ce package.json supporte build TS->JS pour Azure (dist/), avec scripts pour dev/prod. Installez via npm i puis npm run build. Piège : Oubliez pas @types pour IntelliSense ; Azure détecte auto Node via engine dans package.json (ajoutez "engines": {"node": "20.x"} si besoin).
Installer Azure CLI et créer resource group
#!/bin/bash
# Installer Azure CLI si pas présent
curl -sL https://aka.ms/InstallAzureCLIDeb | bash
# Login (utilisez az login --use-device-code pour headless)
az login
# Variables
RESOURCE_GROUP="rg-appservice-demo-$(date +%Y%m%d)"
LOCATION="westeurope"
APP_NAME="demo-app-$(date +%s)"
# Créer resource group
az group create --name $RESOURCE_GROUP --location $LOCATION
echo "Resource group créé: $RESOURCE_GROUP"
echo "App name généré: $APP_NAME"
export RESOURCE_GROUP=$RESOURCE_GROUP
export APP_NAME=$APP_NAMECe script bash installe Azure CLI, logue et crée un RG unique avec timestamp. Exécutez bash setup-azure.sh puis sourcez exports. Piège : Utilisez westeurope pour latence FR ; vérifiez quotas RG avec az group list.
Déployer App Service Plan et app via CLI
#!/bin/bash
source setup-azure.sh
exported
# Créer App Service Plan Premium V3 (autoscaling)
az appservice plan create \
--name ${APP_NAME}-plan \
--resource-group $RESOURCE_GROUP \
--sku P1V3 \
--is-linux
# Créer web app Node.js
az webapp create \
--resource-group $RESOURCE_GROUP \
--plan ${APP_NAME}-plan \
--name $APP_NAME \
--runtime "NODE|20-lts" \
--deployment-local-git
# Config app settings pour scaling demo
az webapp config appsettings set \
--resource-group $RESOURCE_GROUP \
--name $APP_NAME \
--settings REQUEST_COUNT=0 WEBSITE_NODE_DEFAULT_VERSION=20
# Build et ZIP deploy
npm run build
zip -r app.zip .
az webapp deployment source config-zip \
--resource-group $RESOURCE_GROUP \
--name $APP_NAME \
--src app.zip
# URL de l'app
echo "App déployée: https://${APP_NAME}.azurewebsites.net/health"Ce script crée un Plan PremiumV3 Linux (scale-out auto), webapp Node20, set env vars, build/zip et déploie. Testez /health. Piège : PremiumV3 requis pour slots/custom scaling ; ZIP max 2GB, utilisez Git pour >.
Template Bicep pour infrastructure IaC
param location string = resourceGroup().location
param appName string
resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = {
name: '${appName}-plan'
location: location
sku: {
name: 'P1V3'
tier: 'PremiumV3'
}
kind: 'linux'
}
resource appService 'Microsoft.Web/sites@2023-01-01' = {
name: appName
location: location
properties: {
serverFarmId: appServicePlan.id
siteConfig: {
linuxFxVersion: 'NODE|20-lts'
appSettings: [
{ name: 'REQUEST_COUNT', value: '0' }
{ name: 'WEBSITE_RUN_FROM_PACKAGE', value: '1' }
]
}
}
}
output appUrl string = 'https://${appName}.azurewebsites.net'Ce template Bicep déclare Plan et App Service avec settings. Déployez via az deployment group create --resource-group $RESOURCE_GROUP --template-file main.bicep --parameters appName=$APP_NAME. Piège : WEBSITE_RUN_FROM_PACKAGE=1 pour run-from-zip sans warmup ; idempotent, réutilisable en pipelines.
Workflow GitHub Actions pour CI/CD
name: Deploy to Azure App Service
on:
push:
branches: [ main ]
env:
AZURE_WEBAPP_NAME: ${{ secrets.AZURE_WEBAPP_NAME }}
AZURE_WEBAPP_PACKAGE_PATH: 'app.zip'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run build
- run: zip -r ${{ env.AZURE_WEBAPP_PACKAGE_PATH }} .
- uses: actions/upload-artifact@v4
with:
name: app
path: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- download: current
name: Download
uses: actions/download-artifact@v4
with:
name: app
- uses: azure/webapps-deploy@v3
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}Ce workflow build/zip sur push main, utilise OIDC Azure login (via secrets AZURE_CREDENTIALS JSON), déploie ZIP. Ajoutez secrets GitHub. Piège : run-from-package auto avec ZIP ; testez avec act localement.
Créer slot de staging et swap
#!/bin/bash
source setup-azure.sh
exported
# Créer production slot (défaut)
# Créer staging slot
az webapp deployment slot create \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP \
--slot staging
# Déployer sur staging (même ZIP)
zip -r staging.zip .
az webapp deployment source config-zip \
--resource-group $RESOURCE_GROUP \
--name $APP_NAME \
--slot staging \
--src staging.zip
# Test staging
curl https://${APP_NAME}-staging.azurewebsites.net/health
# Swap zero-downtime
az webapp deployment slot swap \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP \
--slot staging \
--target-slot production
echo "Swappé ! Prod: https://${APP_NAME}.azurewebsites.net/health"Slots permettent blue-green : déploie/test sur staging, swap atomique. Piège : Traffic % configurable via az webapp traffic ... ; warmup auto sur Premium.
Bonnes pratiques
- Utilisez toujours slots pour zero-downtime et A/B testing.
- Implémentez KEDA scaling sur métriques custom (CPU >80%, requests/sec) via
az monitor autoscale .... - Intégrez Application Insights :
az webapp config appsettings set APPINSIGHTS_INSTRUMENTATIONKEY=.... - VNet integration pour private endpoints :
az webapp vnet-integration add. - Secrets en Key Vault : Reference via
@Microsoft.KeyVault(...)en Bicep.
Erreurs courantes à éviter
- Oublier Premium Plan : Basic/Shared bloquent slots/autoscale ; upgrade tôt.
- ZIP trop gros : >2GB crash ; passez à Git/Containers.
- Pas de health checks : Probes échouent, app marked unhealthy ; exposez
/health. - Secrets hardcoded : Utilisez App Settings ou KV, jamais en code.
Pour aller plus loin
- Docs officielles : Azure App Service
- Maîtrisez Bicep avancé : Tutoriel Bicep
- KEDA pour scaling events : KEDA on App Service
- Découvrez nos formations Learni DevOps Azure pour certification AZ-204.