Deploy containerized applications to Azure Container Apps using Azure Developer CLI (azd). Use when setting up azd projects, writing azure.yaml configuration, creating Bicep infrastructure for Container Apps, configuring remote builds with ACR, implementing idempotent deployments, managing environment variables across local/.azure/Bicep, or troubleshooting azd up failures. Triggers on requests for azd configuration, Container Apps deployment, multi-service deployments, and infrastructure-as-code
Add this skill
npx mdskills install sickn33/azd-deploymentComprehensive Azure deployment guide with clear instructions, examples, and idempotency patterns
1---2name: azd-deployment3description: Deploy containerized applications to Azure Container Apps using Azure Developer CLI (azd). Use when setting up azd projects, writing azure.yaml configuration, creating Bicep infrastructure for Container Apps, configuring remote builds with ACR, implementing idempotent deployments, managing environment variables across local/.azure/Bicep, or troubleshooting azd up failures. Triggers on requests for azd configuration, Container Apps deployment, multi-service deployments, and infrastructure-as-code with Bicep.4---56# Azure Developer CLI (azd) Container Apps Deployment78Deploy containerized frontend + backend applications to Azure Container Apps with remote builds, managed identity, and idempotent infrastructure.910## Quick Start1112```bash13# Initialize and deploy14azd auth login15azd init # Creates azure.yaml and .azure/ folder16azd env new <env-name> # Create environment (dev, staging, prod)17azd up # Provision infra + build + deploy18```1920## Core File Structure2122```23project/24├── azure.yaml # azd service definitions + hooks25├── infra/26│ ├── main.bicep # Root infrastructure module27│ ├── main.parameters.json # Parameter injection from env vars28│ └── modules/29│ ├── container-apps-environment.bicep30│ └── container-app.bicep31├── .azure/32│ ├── config.json # Default environment pointer33│ └── <env-name>/34│ ├── .env # Environment-specific values (azd-managed)35│ └── config.json # Environment metadata36└── src/37 ├── frontend/Dockerfile38 └── backend/Dockerfile39```4041## azure.yaml Configuration4243### Minimal Configuration4445```yaml46name: azd-deployment47services:48 backend:49 project: ./src/backend50 language: python51 host: containerapp52 docker:53 path: ./Dockerfile54 remoteBuild: true55```5657### Full Configuration with Hooks5859```yaml60name: azd-deployment61metadata:62 template: my-project@1.0.06364infra:65 provider: bicep66 path: ./infra6768azure:69 location: eastus27071services:72 frontend:73 project: ./src/frontend74 language: ts75 host: containerapp76 docker:77 path: ./Dockerfile78 context: .79 remoteBuild: true8081 backend:82 project: ./src/backend83 language: python84 host: containerapp85 docker:86 path: ./Dockerfile87 context: .88 remoteBuild: true8990hooks:91 preprovision:92 shell: sh93 run: |94 echo "Before provisioning..."9596 postprovision:97 shell: sh98 run: |99 echo "After provisioning - set up RBAC, etc."100101 postdeploy:102 shell: sh103 run: |104 echo "Frontend: ${SERVICE_FRONTEND_URI}"105 echo "Backend: ${SERVICE_BACKEND_URI}"106```107108### Key azure.yaml Options109110| Option | Description |111|--------|-------------|112| `remoteBuild: true` | Build images in Azure Container Registry (recommended) |113| `context: .` | Docker build context relative to project path |114| `host: containerapp` | Deploy to Azure Container Apps |115| `infra.provider: bicep` | Use Bicep for infrastructure |116117## Environment Variables Flow118119### Three-Level Configuration1201211. **Local `.env`** - For local development only1222. **`.azure/<env>/.env`** - azd-managed, auto-populated from Bicep outputs1233. **`main.parameters.json`** - Maps env vars to Bicep parameters124125### Parameter Injection Pattern126127```json128// infra/main.parameters.json129{130 "parameters": {131 "environmentName": { "value": "${AZURE_ENV_NAME}" },132 "location": { "value": "${AZURE_LOCATION=eastus2}" },133 "azureOpenAiEndpoint": { "value": "${AZURE_OPENAI_ENDPOINT}" }134 }135}136```137138Syntax: `${VAR_NAME}` or `${VAR_NAME=default_value}`139140### Setting Environment Variables141142```bash143# Set for current environment144azd env set AZURE_OPENAI_ENDPOINT "https://my-openai.openai.azure.com"145azd env set AZURE_SEARCH_ENDPOINT "https://my-search.search.windows.net"146147# Set during init148azd env new prod149azd env set AZURE_OPENAI_ENDPOINT "..."150```151152### Bicep Output → Environment Variable153154```bicep155// In main.bicep - outputs auto-populate .azure/<env>/.env156output SERVICE_FRONTEND_URI string = frontend.outputs.uri157output SERVICE_BACKEND_URI string = backend.outputs.uri158output BACKEND_PRINCIPAL_ID string = backend.outputs.principalId159```160161## Idempotent Deployments162163### Why azd up is Idempotent1641651. **Bicep is declarative** - Resources reconcile to desired state1662. **Remote builds tag uniquely** - Image tags include deployment timestamp1673. **ACR reuses layers** - Only changed layers upload168169### Preserving Manual Changes170171Custom domains added via Portal can be lost on redeploy. Preserve with hooks:172173```yaml174hooks:175 preprovision:176 shell: sh177 run: |178 # Save custom domains before provision179 if az containerapp show --name "$FRONTEND_NAME" -g "$RG" &>/dev/null; then180 az containerapp show --name "$FRONTEND_NAME" -g "$RG" \181 --query "properties.configuration.ingress.customDomains" \182 -o json > /tmp/domains.json183 fi184185 postprovision:186 shell: sh187 run: |188 # Verify/restore custom domains189 if [ -f /tmp/domains.json ]; then190 echo "Saved domains: $(cat /tmp/domains.json)"191 fi192```193194### Handling Existing Resources195196```bicep197// Reference existing ACR (don't recreate)198resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-07-01' existing = {199 name: containerRegistryName200}201202// Set customDomains to null to preserve Portal-added domains203customDomains: empty(customDomainsParam) ? null : customDomainsParam204```205206## Container App Service Discovery207208Internal HTTP routing between Container Apps in same environment:209210```bicep211// Backend reference in frontend env vars212env: [213 {214 name: 'BACKEND_URL'215 value: 'http://ca-backend-${resourceToken}' // Internal DNS216 }217]218```219220Frontend nginx proxies to internal URL:221```nginx222location /api {223 proxy_pass $BACKEND_URL;224}225```226227## Managed Identity & RBAC228229### Enable System-Assigned Identity230231```bicep232resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {233 identity: {234 type: 'SystemAssigned'235 }236}237238output principalId string = containerApp.identity.principalId239```240241### Post-Provision RBAC Assignment242243```yaml244hooks:245 postprovision:246 shell: sh247 run: |248 PRINCIPAL_ID="${BACKEND_PRINCIPAL_ID}"249250 # Azure OpenAI access251 az role assignment create \252 --assignee-object-id "$PRINCIPAL_ID" \253 --assignee-principal-type ServicePrincipal \254 --role "Cognitive Services OpenAI User" \255 --scope "$OPENAI_RESOURCE_ID" 2>/dev/null || true256257 # Azure AI Search access258 az role assignment create \259 --assignee-object-id "$PRINCIPAL_ID" \260 --role "Search Index Data Reader" \261 --scope "$SEARCH_RESOURCE_ID" 2>/dev/null || true262```263264## Common Commands265266```bash267# Environment management268azd env list # List environments269azd env select <name> # Switch environment270azd env get-values # Show all env vars271azd env set KEY value # Set variable272273# Deployment274azd up # Full provision + deploy275azd provision # Infrastructure only276azd deploy # Code deployment only277azd deploy --service backend # Deploy single service278279# Debugging280azd show # Show project status281az containerapp logs show -n <app> -g <rg> --follow # Stream logs282```283284## Reference Files285286- **Bicep patterns**: See [references/bicep-patterns.md](references/bicep-patterns.md) for Container Apps modules287- **Troubleshooting**: See [references/troubleshooting.md](references/troubleshooting.md) for common issues288- **azure.yaml schema**: See [references/azure-yaml-schema.md](references/azure-yaml-schema.md) for full options289290## Critical Reminders2912921. **Always use `remoteBuild: true`** - Local builds fail on M1/ARM Macs deploying to AMD642932. **Bicep outputs auto-populate .azure/<env>/.env** - Don't manually edit2943. **Use `azd env set` for secrets** - Not main.parameters.json defaults2954. **Service tags (`azd-service-name`)** - Required for azd to find Container Apps2965. **`|| true` in hooks** - Prevent RBAC "already exists" errors from failing deploy297
Full transparency — inspect the skill content before installing.