| name | azure-app-service |
| description | Deploy and manage web apps using Azure App Service with auto-scaling, deployment slots, SSL/TLS, and monitoring. Use for hosting web applications on Azure. |
Azure App Service
Overview
Azure App Service provides a fully managed platform for building and hosting web applications, REST APIs, and mobile backends. Support multiple programming languages with integrated DevOps, security, and high availability.
When to Use
- Web applications (ASP.NET, Node.js, Python, Java)
- REST APIs and microservices
- Mobile app backends
- Static website hosting
- Production applications requiring scale
- Applications needing auto-scaling
- Multi-region deployments
- Containerized applications
Implementation Examples
1. App Service Creation with Azure CLI
# Login to Azure
az login
# Create resource group
az group create --name myapp-rg --location eastus
# Create App Service Plan
az appservice plan create \
--name myapp-plan \
--resource-group myapp-rg \
--sku P1V2 \
--is-linux
# Create web app
az webapp create \
--resource-group myapp-rg \
--plan myapp-plan \
--name myapp-web \
--deployment-container-image-name nodejs:18
# Configure app settings
az webapp config appsettings set \
--resource-group myapp-rg \
--name myapp-web \
--settings \
NODE_ENV=production \
PORT=8080 \
DATABASE_URL=postgresql://... \
REDIS_URL=redis://...
# Enable HTTPS only
az webapp update \
--resource-group myapp-rg \
--name myapp-web \
--https-only true
# Configure custom domain
az webapp config hostname add \
--resource-group myapp-rg \
--webapp-name myapp-web \
--hostname www.example.com
# Create deployment slot
az webapp deployment slot create \
--resource-group myapp-rg \
--name myapp-web \
--slot staging
# Swap slots
az webapp deployment slot swap \
--resource-group myapp-rg \
--name myapp-web \
--slot staging
# Get publish profile for deployment
az webapp deployment list-publish-profiles \
--resource-group myapp-rg \
--name myapp-web \
--query "[0].publishUrl"
2. Terraform App Service Configuration
# app-service.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}
provider "azurerm" {
features {}
}
variable "environment" {
default = "prod"
}
variable "location" {
default = "eastus"
}
# Resource group
resource "azurerm_resource_group" "main" {
name = "myapp-rg-${var.environment}"
location = var.location
}
# App Service Plan
resource "azurerm_service_plan" "main" {
name = "myapp-plan-${var.environment}"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
os_type = "Linux"
sku_name = "P1V2"
tags = {
environment = var.environment
}
}
# Log Analytics Workspace
resource "azurerm_log_analytics_workspace" "main" {
name = "myapp-logs-${var.environment}"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
sku = "PerGB2018"
retention_in_days = 30
}
# Application Insights
resource "azurerm_application_insights" "main" {
name = "myapp-insights-${var.environment}"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
application_type = "web"
retention_in_days = 30
workspace_id = azurerm_log_analytics_workspace.main.id
}
# Web App
resource "azurerm_linux_web_app" "main" {
name = "myapp-web-${var.environment}"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
service_plan_id = azurerm_service_plan.main.id
https_only = true
app_settings = {
WEBSITES_ENABLE_APP_SERVICE_STORAGE = false
DOCKER_ENABLE_CI = true
APPINSIGHTS_INSTRUMENTATIONKEY = azurerm_application_insights.main.instrumentation_key
APPLICATIONINSIGHTS_CONNECTION_STRING = azurerm_application_insights.main.connection_string
NODE_ENV = "production"
PORT = "8080"
}
site_config {
always_on = true
http2_enabled = true
minimum_tls_version = "1.2"
websockets_enabled = false
application_stack {
node_version = "18-lts"
}
cors {
allowed_origins = ["https://example.com"]
}
}
identity {
type = "SystemAssigned"
}
tags = {
environment = var.environment
}
}
# Deployment slot (staging)
resource "azurerm_linux_web_app_slot" "staging" {
name = "staging"
app_service_id = azurerm_linux_web_app.main.id
service_plan_id = azurerm_service_plan.main.id
https_only = true
app_settings = {
WEBSITES_ENABLE_APP_SERVICE_STORAGE = false
NODE_ENV = "staging"
PORT = "8080"
}
site_config {
always_on = true
http2_enabled = true
minimum_tls_version = "1.2"
application_stack {
node_version = "18-lts"
}
}
identity {
type = "SystemAssigned"
}
}
# Autoscale settings
resource "azurerm_monitor_autoscale_setting" "app_service" {
name = "app-service-autoscale"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
target_resource_id = azurerm_service_plan.main.id
profile {
name = "default"
capacity {
default = 2
minimum = 1
maximum = 5
}
rule {
metric_trigger {
metric_name = "CpuPercentage"
metric_resource_id = azurerm_service_plan.main.id
time_grain = "PT1M"
statistic = "Average"
time_window = "PT5M"
operator = "GreaterThan"
threshold = 75
}
scale_action {
direction = "Increase"
type = "ChangeCount"
value = 1
cooldown = "PT5M"
}
}
rule {
metric_trigger {
metric_name = "CpuPercentage"
metric_resource_id = azurerm_service_plan.main.id
time_grain = "PT1M"
statistic = "Average"
time_window = "PT5M"
operator = "LessThan"
threshold = 25
}
scale_action {
direction = "Decrease"
type = "ChangeCount"
value = 1
cooldown = "PT5M"
}
}
}
}
# Diagnostic settings
resource "azurerm_monitor_diagnostic_setting" "app_service" {
name = "app-service-logs"
target_resource_id = azurerm_linux_web_app.main.id
log_analytics_workspace_id = azurerm_log_analytics_workspace.main.id
enabled_log {
category = "AppServiceHTTPLogs"
}
enabled_log {
category = "AppServiceAntivirusScanAuditLogs"
}
metric {
category = "AllMetrics"
}
}
# Key Vault for secrets
resource "azurerm_key_vault" "main" {
name = "myappkv${var.environment}"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
access_policy {
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = azurerm_linux_web_app.main.identity[0].principal_id
secret_permissions = [
"Get",
"List"
]
}
tags = {
environment = var.environment
}
}
# Key Vault secrets
resource "azurerm_key_vault_secret" "database_url" {
name = "database-url"
value = "postgresql://user:pass@host/db"
key_vault_id = azurerm_key_vault.main.id
}
resource "azurerm_key_vault_secret" "api_key" {
name = "api-key"
value = "your-api-key-here"
key_vault_id = azurerm_key_vault.main.id
}
data "azurerm_client_config" "current" {}
output "app_url" {
value = "https://${azurerm_linux_web_app.main.default_hostname}"
}
output "app_insights_key" {
value = azurerm_application_insights.main.instrumentation_key
sensitive = true
}
3. Deployment Configuration
# .github/workflows/deploy.yml
name: Deploy to App Service
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
- name: Build
run: npm run build
- name: Deploy to Azure
uses: azure/webapps-deploy@v2
with:
app-name: myapp-web-prod
publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE }}
package: .
- name: Swap slots
uses: azure/CLI@v1
with:
azcliversion: 2.0.76
inlineScript: |
az webapp deployment slot swap \
--resource-group myapp-rg-prod \
--name myapp-web-prod \
--slot staging
4. Health Check Configuration
# Enable health check
az webapp config set \
--resource-group myapp-rg \
--name myapp-web \
--generic-configurations HEALTHCHECK_PATH=/health
# Monitor health
az monitor metrics list-definitions \
--resource /subscriptions/{subscription}/resourceGroups/myapp-rg/providers/Microsoft.Web/sites/myapp-web
Best Practices
✅ DO
- Use deployment slots for zero-downtime deployments
- Enable Application Insights
- Configure autoscaling based on metrics
- Use managed identity for Azure services
- Enable HTTPS only
- Store secrets in Key Vault
- Monitor performance metrics
- Implement health checks
❌ DON'T
- Store secrets in configuration
- Disable HTTPS
- Ignore Application Insights
- Use single instance for production
- Deploy directly to production
- Ignore autoscaling configuration
Monitoring
- Application Insights for application metrics
- Azure Monitor for resource health
- Log Analytics for log analysis
- Custom metrics and events
- Performance counters and diagnostics