Azure
intermediate
40-50 minutes
Advanced Azure Features
Master Azure SQL databases, Blob Storage, Key Vault, custom domains, monitoring, and production best practices.
What you'll accomplish
Production-ready Azure deployment with database, storage, secrets, and monitoring
Prerequisites
- Application deployed to Azure
- Basic understanding of Azure core concepts
Azure SQL Database
Fully managed SQL Server database.
Create SQL Server and Database
bash# Create SQL Server az sql server create \ --name myapp-sqlserver \ --resource-group myapp-rg \ --location eastus \ --admin-user sqladmin \ --admin-password "SecureP@ssw0rd123!" # Create database az sql db create \ --name myappdb \ --server myapp-sqlserver \ --resource-group myapp-rg \ --edition Basic \ --capacity 5 # For production az sql db create \ --name myappdb \ --server myapp-sqlserver \ --resource-group myapp-rg \ --edition Standard \ --service-objective S1
Pricing Tiers
| Tier | DTUs/vCores | Use Case |
|---|---|---|
| Basic | 5 DTU | Dev/test |
| Standard S0 | 10 DTU | Light production |
| Standard S1 | 20 DTU | Small apps |
| Standard S2 | 50 DTU | Medium apps |
| Premium P1 | 125 DTU | High performance |
Configure Firewall
bash# Allow Azure services az sql server firewall-rule create \ --server myapp-sqlserver \ --resource-group myapp-rg \ --name AllowAzureServices \ --start-ip-address 0.0.0.0 \ --end-ip-address 0.0.0.0 # Allow your IP az sql server firewall-rule create \ --server myapp-sqlserver \ --resource-group myapp-rg \ --name AllowMyIP \ --start-ip-address YOUR_IP \ --end-ip-address YOUR_IP
Connect from App Service
bash# Get connection string az sql db show-connection-string \ --server myapp-sqlserver \ --name myappdb \ --client ado.net # Set as connection string in App Service az webapp config connection-string set \ --name myapp \ --resource-group myapp-rg \ --connection-string-type SQLAzure \ --settings DefaultConnection="Server=tcp:myapp-sqlserver.database.windows.net,1433;Database=myappdb;User ID=sqladmin;Password=YOUR_PASSWORD;Encrypt=true;"
PostgreSQL Alternative
bash# Create PostgreSQL server az postgres flexible-server create \ --name myapp-postgres \ --resource-group myapp-rg \ --location eastus \ --admin-user pgadmin \ --admin-password "SecureP@ssw0rd123!" \ --sku-name Standard_B1ms \ --tier Burstable # Create database az postgres flexible-server db create \ --server-name myapp-postgres \ --resource-group myapp-rg \ --database-name myappdb
Azure Blob Storage
Object storage for files, images, and backups.
Create Storage Account
bash# Create storage account az storage account create \ --name myappstorage123 \ --resource-group myapp-rg \ --location eastus \ --sku Standard_LRS \ --kind StorageV2 # Get connection string az storage account show-connection-string \ --name myappstorage123 \ --resource-group myapp-rg \ --query connectionString \ --output tsv
Create Container
bash# Get storage key STORAGE_KEY=$(az storage account keys list \ --account-name myappstorage123 \ --query "[0].value" \ --output tsv) # Create container az storage container create \ --name uploads \ --account-name myappstorage123 \ --account-key $STORAGE_KEY \ --public-access off
Upload and Download Files
bash# Upload file az storage blob upload \ --account-name myappstorage123 \ --container-name uploads \ --name myfile.txt \ --file ./local-file.txt \ --account-key $STORAGE_KEY # List blobs az storage blob list \ --account-name myappstorage123 \ --container-name uploads \ --output table # Download file az storage blob download \ --account-name myappstorage123 \ --container-name uploads \ --name myfile.txt \ --file ./downloaded-file.txt \ --account-key $STORAGE_KEY
Generate SAS Token
bash# Generate SAS for container END_DATE=$(date -u -d "+1 year" +%Y-%m-%dT%H:%MZ) az storage container generate-sas \ --account-name myappstorage123 \ --name uploads \ --permissions rwl \ --expiry $END_DATE \ --account-key $STORAGE_KEY
Static Website Hosting
bash# Enable static website az storage blob service-properties update \ --account-name myappstorage123 \ --static-website \ --index-document index.html \ --404-document 404.html # Upload files az storage blob upload-batch \ --account-name myappstorage123 \ --source ./dist \ --destination '$web' # Get website URL az storage account show \ --name myappstorage123 \ --query "primaryEndpoints.web" \ --output tsv
Azure Key Vault
Secure storage for secrets, keys, and certificates.
Create Key Vault
bashaz keyvault create \ --name myapp-keyvault \ --resource-group myapp-rg \ --location eastus
Store and Retrieve Secrets
bash# Add secret az keyvault secret set \ --vault-name myapp-keyvault \ --name "DatabasePassword" \ --value "supersecret123" # Get secret az keyvault secret show \ --vault-name myapp-keyvault \ --name "DatabasePassword" \ --query value \ --output tsv # List secrets az keyvault secret list \ --vault-name myapp-keyvault \ --output table
Access from App Service
bash# Enable managed identity az webapp identity assign \ --name myapp \ --resource-group myapp-rg # Get identity principal ID PRINCIPAL_ID=$(az webapp identity show \ --name myapp \ --resource-group myapp-rg \ --query principalId \ --output tsv) # Grant access to Key Vault az keyvault set-policy \ --name myapp-keyvault \ --object-id $PRINCIPAL_ID \ --secret-permissions get list # Reference secret in app settings az webapp config appsettings set \ --name myapp \ --resource-group myapp-rg \ --settings "[email protected](SecretUri=https://myapp-keyvault.vault.azure.net/secrets/DatabasePassword/)"
Custom Domains and SSL
Add Custom Domain to App Service
bash# Add custom hostname az webapp config hostname add \ --webapp-name myapp \ --resource-group myapp-rg \ --hostname www.example.com
DNS Configuration
At your DNS provider:
| Type | Name | Value |
|---|---|---|
| CNAME | www | myapp.azurewebsites.net |
| TXT | asuid.www | (from Azure verification) |
For apex domain:
| Type | Name | Value |
|---|---|---|
| A | @ | App Service IP |
| TXT | asuid | (from Azure verification) |
Free Managed SSL
bash# Create managed certificate az webapp config ssl create \ --name myapp \ --resource-group myapp-rg \ --hostname www.example.com # Bind certificate az webapp config ssl bind \ --name myapp \ --resource-group myapp-rg \ --certificate-thumbprint THUMBPRINT \ --ssl-type SNI # Enforce HTTPS az webapp update \ --name myapp \ --resource-group myapp-rg \ --https-only true
Application Insights
Full application monitoring.
Enable Application Insights
bash# Create Application Insights az monitor app-insights component create \ --app myapp-insights \ --resource-group myapp-rg \ --location eastus \ --application-type web # Get instrumentation key az monitor app-insights component show \ --app myapp-insights \ --resource-group myapp-rg \ --query instrumentationKey \ --output tsv # Connect to App Service az monitor app-insights component connect-webapp \ --app myapp-insights \ --resource-group myapp-rg \ --web-app myapp
View Metrics
bash# Query metrics az monitor app-insights metrics show \ --app myapp-insights \ --resource-group myapp-rg \ --metric requests/count \ --interval PT1H
Create Alerts
bash# Create alert for high error rate az monitor metrics alert create \ --name "High Error Rate" \ --resource-group myapp-rg \ --scopes /subscriptions/.../resourceGroups/myapp-rg/providers/Microsoft.Web/sites/myapp \ --condition "total requests/failed > 10" \ --window-size 5m \ --evaluation-frequency 1m
Azure Monitor and Logging
Enable Diagnostic Logs
bash# Enable all logs az webapp log config \ --name myapp \ --resource-group myapp-rg \ --application-logging filesystem \ --detailed-error-messages true \ --failed-request-tracing true \ --web-server-logging filesystem \ --level information # Stream logs az webapp log tail \ --name myapp \ --resource-group myapp-rg
Log Analytics Workspace
bash# Create workspace az monitor log-analytics workspace create \ --workspace-name myapp-logs \ --resource-group myapp-rg \ --location eastus # Query logs az monitor log-analytics query \ --workspace myapp-logs \ --analytics-query "AppServiceHTTPLogs | where ScStatus >= 500 | take 10"
Azure Front Door (CDN)
Global CDN and load balancing.
bash# Create Front Door profile az afd profile create \ --profile-name myapp-frontdoor \ --resource-group myapp-rg \ --sku Standard_AzureFrontDoor # Create endpoint az afd endpoint create \ --endpoint-name myapp-endpoint \ --profile-name myapp-frontdoor \ --resource-group myapp-rg # Create origin group az afd origin-group create \ --origin-group-name myapp-origin-group \ --profile-name myapp-frontdoor \ --resource-group myapp-rg \ --probe-path /health \ --probe-protocol Https \ --probe-request-type HEAD \ --probe-interval-in-seconds 30 # Add origin az afd origin create \ --origin-name myapp-origin \ --origin-group-name myapp-origin-group \ --profile-name myapp-frontdoor \ --resource-group myapp-rg \ --host-name myapp.azurewebsites.net \ --origin-host-header myapp.azurewebsites.net \ --http-port 80 \ --https-port 443 \ --priority 1 \ --weight 1000 # Create route az afd route create \ --route-name myapp-route \ --endpoint-name myapp-endpoint \ --profile-name myapp-frontdoor \ --resource-group myapp-rg \ --origin-group myapp-origin-group \ --patterns-to-match "/*" \ --supported-protocols Https \ --https-redirect Enabled
Azure Backup
App Service Backup
bash# Create storage container for backups az storage container create \ --name backups \ --account-name myappstorage123 # Configure backup az webapp config backup create \ --webapp-name myapp \ --resource-group myapp-rg \ --container-url "https://myappstorage123.blob.core.windows.net/backups?SAS_TOKEN" \ --frequency 1d \ --retain-one true
Database Backup
Azure SQL has automatic backups:
- Point-in-time restore (7-35 days)
- Long-term retention (up to 10 years)
bash# Configure long-term retention az sql db ltr-policy set \ --server myapp-sqlserver \ --database myappdb \ --resource-group myapp-rg \ --weekly-retention P4W \ --monthly-retention P12M \ --yearly-retention P5Y \ --week-of-year 1
Cost Management
Set Budget
bashaz consumption budget create \ --amount 100 \ --budget-name "Monthly Budget" \ --category Cost \ --resource-group myapp-rg \ --time-grain Monthly \ --time-period start-date=$(date +%Y-%m-01) \ --notifications type="Actual" contact-emails="[email protected]" threshold=80
View Costs
bash# Get current costs az consumption usage list \ --start-date $(date -d "-7 days" +%Y-%m-%d) \ --end-date $(date +%Y-%m-%d) \ --output table
Cost Saving Tips
- Use reserved instances - Up to 72% savings
- Right-size resources - Monitor and adjust
- Use dev/test subscriptions - Lower rates
- Auto-shutdown VMs - Off-hours savings
- Use serverless - Pay per execution
- Delete unused resources - IPs, disks, snapshots
Production Checklist
Security
- Enable managed identity
- Store secrets in Key Vault
- Configure HTTPS only
- Set up firewall rules
- Enable Azure AD authentication
- Review RBAC permissions
Reliability
- Configure auto-scaling
- Set up deployment slots
- Enable health checks
- Configure database backups
- Test disaster recovery
Performance
- Enable Azure CDN/Front Door
- Configure caching headers
- Use connection pooling
- Optimize database queries
- Monitor Application Insights
Monitoring
- Enable Application Insights
- Configure alerts
- Set up Log Analytics
- Create dashboards
- Set budget alerts
Deployment
- Set up CI/CD pipeline
- Use staging slots
- Implement health checks
- Configure rollback strategy
Complete Production Setup
bash#!/bin/bash set -e RESOURCE_GROUP="myapp-prod-rg" LOCATION="eastus" APP_NAME="myapp-prod" # Create resource group az group create --name $RESOURCE_GROUP --location $LOCATION # Create App Service plan az appservice plan create \ --name ${APP_NAME}-plan \ --resource-group $RESOURCE_GROUP \ --sku S1 \ --is-linux # Create web app az webapp create \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --plan ${APP_NAME}-plan \ --runtime "NODE:20-lts" # Enable managed identity az webapp identity assign \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP # Create Key Vault az keyvault create \ --name ${APP_NAME}-kv \ --resource-group $RESOURCE_GROUP \ --location $LOCATION # Grant Key Vault access PRINCIPAL_ID=$(az webapp identity show \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --query principalId -o tsv) az keyvault set-policy \ --name ${APP_NAME}-kv \ --object-id $PRINCIPAL_ID \ --secret-permissions get list # Create SQL Database az sql server create \ --name ${APP_NAME}-sql \ --resource-group $RESOURCE_GROUP \ --location $LOCATION \ --admin-user sqladmin \ --admin-password "$(openssl rand -base64 24)" az sql db create \ --name ${APP_NAME}db \ --server ${APP_NAME}-sql \ --resource-group $RESOURCE_GROUP \ --edition Standard \ --service-objective S1 # Create storage account az storage account create \ --name ${APP_NAME}storage \ --resource-group $RESOURCE_GROUP \ --sku Standard_LRS # Create Application Insights az monitor app-insights component create \ --app ${APP_NAME}-insights \ --resource-group $RESOURCE_GROUP \ --location $LOCATION \ --application-type web az monitor app-insights component connect-webapp \ --app ${APP_NAME}-insights \ --resource-group $RESOURCE_GROUP \ --web-app $APP_NAME # Enable HTTPS only az webapp update \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --https-only true # Enable always on az webapp config set \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --always-on true echo "Production setup complete!" echo "App URL: https://${APP_NAME}.azurewebsites.net"
Note
Checkpoint: Set up Azure SQL, configure Key Vault for secrets, enable Application Insights, and verify your production checklist is complete.