All skills
microsoft avatar

/azure-deploy

@b3c238e
by microsoftmicrosoft/skills3.1k stars
351

Execute Azure deployments for ALREADY-PREPARED applications that have existing .azure/deployment-plan.md and infrastructure files. DO NOT use this skill when the user asks to CREATE a new application — use azure-prepare instead. This skill runs azd up, azd deploy, terraform apply, and az deployment commands with built-in error recovery. Requires .azure/deployment-plan.md from azure-prepare and validated status from azure-validate. WHEN: "run azd up", "run azd deploy", "execute deployment", "push to production", "push to cloud", "go live", "ship it", "bicep deploy", "terraform apply", "publish to Azure", "launch on Azure". DO NOT USE WHEN: "create and deploy", "build and deploy", "create a new app", "set up infrastructure", "create and deploy to Azure using Terraform" — use azure-prepare for these.

Use this Skill: https://skilld.dev/gh/microsoft/skills/azure-deploy

This session only. Nothing lands on disk.

referencesrecipesazderrors.md

≈4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

AZD Errors

Deployment Runtime Errors

These errors occur during azd up execution:

Error Cause Resolution
unknown flag: --location azd up doesn't accept --location Use azd env set AZURE_LOCATION <region> before azd up
Provision failed Bicep template errors Check detailed error in output
Deploy failed Build or Docker errors Check build logs
Package failed Missing Dockerfile or deps Verify Dockerfile exists and dependencies
Quota exceeded Subscription limits Request increase or change region
PrincipalId '...' has type 'ServicePrincipal', which is different from specified PrincipalType 'User' Base template RBAC assigns roles with principalType: 'User' but deploying identity is a service principal (CI/CD) Set allowUserIdentityPrincipal: false in the storageEndpointConfig variable in infra/main.bicep. Do NOT try clearing AZURE_PRINCIPAL_ID — azd repopulates it. See Principal Type Mismatch.
ImagePullBackOff or azd up hangs during provision for Container Apps Container App references an image that doesn't exist in ACR yet See Container Apps Bootstrap Problem
unauthorized: authentication required on docker push to ACR ACR auth token expired or scoped incorrectly See ACR Authentication Failures
could not determine container registry endpoint Missing AZURE_CONTAINER_REGISTRY_ENDPOINT See Missing Container Registry Variables
map has no entry for key "AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID" Missing managed identity env vars See Missing Container Registry Variables
map has no entry for key "MANAGED_IDENTITY_CLIENT_ID" Missing managed identity client ID See Missing Container Registry Variables
Operation expired / revision creation timeout (900s) RBAC propagation delay — Container App's managed identity doesn't have AcrPull on ACR yet See Container App Revision Timeout
found '2' resources tagged with 'azd-service-name: <name>' Previous deployment left duplicate-tagged resources in same RG Preferred: Create fresh env with azd env new <new-name> --no-prompt, set subscription/location, redeploy. Alternative: Delete conflicting resources (requires ask_user).
Literal {{ .Env.* }} in Terraform errors azd does not interpolate template variables in .tfvars.json See Unresolved Terraform Template Variables

ℹ️ Pre-flight validation: Run azure-validate before deployment to catch configuration errors early. See Pre-Deploy Checklist.

Container App Revision Timeout

Symptom: azd up provisions infrastructure successfully but the Container App revision creation times out after ~900 seconds. The Container App enters a Failed provisioning state with no active revision. The azd output shows Operation expired or The operation did not complete within the permitted time.

Cause: Azure RBAC propagation delay. When azd up runs both azd provision and azd deploy in a single step:

  1. Bicep creates the Container App with a system-assigned managed identity and a public placeholder image
  2. Bicep creates an AcrPull role assignment for that identity on ACR in a separate module using the two-phase deployment pattern
  3. azd deploy immediately pushes the real image and creates a new Container App revision
  4. The revision tries to pull the image from ACR, but the AcrPull role assignment hasn't propagated yet (can take 1–5 minutes)
  5. The image pull fails repeatedly until the 900-second timeout is reached

Solution:

  1. Verify the Container App state:
az containerapp show --name <app-name> --resource-group <resource-group> \
  --query "{provisioningState:properties.provisioningState, latestRevision:properties.latestRevisionName}" -o json
  1. Confirm the AcrPull role exists (it may have propagated by now):
PRINCIPAL_ID=$(az containerapp identity show --name <app-name> --resource-group <resource-group> --query principalId -o tsv)
az role assignment list --scope $(az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv) \
  --assignee-object-id "$PRINCIPAL_ID" --query "[].roleDefinitionName" -o tsv

PowerShell:

$PrincipalId = az containerapp identity show --name <app-name> --resource-group <resource-group> --query principalId -o tsv
$AcrScope = az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv
az role assignment list --scope $AcrScope --assignee-object-id $PrincipalId --query "[].roleDefinitionName" -o tsv
  1. If AcrPull is missing, assign it:
az role assignment create \
  --assignee-object-id "$PRINCIPAL_ID" \
  --assignee-principal-type ServicePrincipal \
  --role AcrPull \
  --scope $(az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv)

PowerShell:

$AcrScope = az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv
az role assignment create `
  --assignee-object-id $PrincipalId `
  --assignee-principal-type ServicePrincipal `
  --role AcrPull `
  --scope $AcrScope
  1. Wait for propagation, then redeploy:
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT $(az acr show --name <acr-name> --resource-group <resource-group> --query loginServer -o tsv)

for attempt in 1 2 3 4 5; do
  echo "Waiting for RBAC propagation (attempt $attempt/5)..."
  sleep 60

  if azd deploy --no-prompt; then
    echo "Deployment succeeded after RBAC propagation."
    break
  fi

  if [ "$attempt" -eq 5 ]; then
    echo "Deployment still failing after 5 minutes. Re-check AcrPull assignment and Container App revision status."
    exit 1
  fi
done

PowerShell:

azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT (az acr show --name <acr-name> --resource-group <resource-group> --query loginServer -o tsv)

for ($attempt = 1; $attempt -le 5; $attempt++) {
    Write-Output "Waiting for RBAC propagation (attempt $attempt/5)..."
    Start-Sleep -Seconds 60

    azd deploy --no-prompt
    if ($LASTEXITCODE -eq 0) {
        Write-Output "Deployment succeeded after RBAC propagation."
        break
    }

    if ($attempt -eq 5) {
        Write-Output "Deployment still failing after 5 minutes. Re-check AcrPull assignment and Container App revision status."
        exit 1
    }
}

💡 Prevention: To avoid this in future deployments, ensure the Bicep template includes the AcrPull role assignment with principalType: 'ServicePrincipal', and consider using azd provision + azd deploy as separate steps instead of azd up to allow RBAC propagation time between infrastructure creation and app deployment.

Container Apps Bootstrap Problem

Symptom: azd up hangs or fails during provisioning with ImagePullBackOff, or the Container App cannot start because the referenced image doesn't exist in ACR yet.

Cause: The Bicep template creates the Container App referencing an ACR image, but that image doesn't exist until azd deploy builds and pushes it. This chicken-and-egg problem blocks provisioning.

Solution — use two-phase deployment:

# Phase 1: Provision infrastructure (Container App uses placeholder image)
azd provision --no-prompt

# Phase 2: Build, push, and update Container App with real image
azd deploy --no-prompt

⚠️ This requires the Bicep template to use a placeholder image parameter (e.g., mcr.microsoft.com/azuredocs/containerapps-helloworld:latest) so provisioning succeeds without the app image. If the Bicep hardcodes the ACR image reference, update it to accept a containerImageName parameter with a placeholder default before provisioning.

⚠️ Do NOT repeatedly poll a hanging azd up — if there is no provisioning progress or you continue to see ImagePullBackOff events for several minutes during a Container Apps deployment, stop it and switch to the two-phase approach above.

ACR Authentication Failures

Symptom: docker push fails with unauthorized: authentication required even after az acr login succeeds.

Solution — try these methods in order:

# Method 1: AAD-based login (preferred)
az acr login --name <acr-name>
docker push <acr-name>.azurecr.io/<image>:<tag>

# Method 2: Admin credentials (fallback)
ACR_USER=$(az acr credential show --name <acr-name> --query username -o tsv)
ACR_PASS=$(az acr credential show --name <acr-name> --query "passwords[0].value" -o tsv)
docker login <acr-name>.azurecr.io -u "$ACR_USER" -p "$ACR_PASS"
docker push <acr-name>.azurecr.io/<image>:<tag>

PowerShell (Method 2):

$AcrUser = az acr credential show --name <acr-name> --query username -o tsv
$AcrPass = az acr credential show --name <acr-name> --query "passwords[0].value" -o tsv
docker login <acr-name>.azurecr.io -u $AcrUser -p $AcrPass
docker push <acr-name>.azurecr.io/<image>:<tag>

💡 Tip: Prefer azd deploy over manual docker push — azd handles ACR authentication automatically.

Missing Container Registry Variables

Symptom: Errors during azd deploy about missing container registry or managed identity environment variables:

ERROR: could not determine container registry endpoint, ensure 'registry' has been set in the docker options or 'AZURE_CONTAINER_REGISTRY_ENDPOINT' environment variable has been set

Or:

ERROR: failed executing template file: template: manifest template:6:14: executing "manifest template" at <.Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID>: map has no entry for key "AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID"

Or:

ERROR: failed executing template file: template: manifest template:39:26: executing "manifest template" at <.Env.MANAGED_IDENTITY_CLIENT_ID>: map has no entry for key "MANAGED_IDENTITY_CLIENT_ID"

Cause: This typically occurs with .NET Aspire projects using azd "limited mode" (in-memory infrastructure generation without explicit infra/ folder). The azd provision command creates the Azure Container Registry and Managed Identity resources but doesn't automatically populate the environment variables that azd deploy needs to reference them.

⚠️ Prevention is Better: For .NET Aspire projects, this issue should be addressed PROACTIVELY before deployment by setting up environment variables after azd init but before azd up. This avoids deployment failures entirely.

Solution:

After azd provision succeeds, manually set the missing environment variables by querying the provisioned resources:

# Get the resource group name (typically rg-{environment-name})
azd env get-values

# Set container registry endpoint
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT $(az acr list --resource-group <resource-group-name> --query "[0].loginServer" -o tsv)

# Set managed identity resource ID
azd env set AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID $(az identity list --resource-group <resource-group-name> --query "[0].id" -o tsv)

# Set managed identity client ID
azd env set MANAGED_IDENTITY_CLIENT_ID $(az identity list --resource-group <resource-group-name> --query "[0].clientId" -o tsv)

PowerShell:

# Set container registry endpoint
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT (az acr list --resource-group <resource-group-name> --query "[0].loginServer" -o tsv)

# Set managed identity resource ID
azd env set AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID (az identity list --resource-group <resource-group-name> --query "[0].id" -o tsv)

# Set managed identity client ID
azd env set MANAGED_IDENTITY_CLIENT_ID (az identity list --resource-group <resource-group-name> --query "[0].clientId" -o tsv)

After setting these variables, retry the deployment:

azd deploy --no-prompt

💡 Tip: This issue is specific to Aspire limited mode. Manually setting these environment variables after azd provision is the recommended workaround.

Unresolved Terraform Template Variables

Symptom: Terraform receives literal Go-style template strings instead of resolved values during azd provision:

Error: Invalid value for variable "environment_name"
  The value "{{ .Env.AZURE_ENV_NAME }}" is not valid.

Or Terraform silently uses the literal string, causing resource naming failures, state conflicts, and cascading errors that lead to deployment timeouts.

Cause: azd reads infra/main.tfvars.json, substitutes ${VAR} references using its built-in envsubst, and passes the resolved file to Terraform via -var-file=. Go-style {{ .Env.* }} variables are only processed in azure.yaml and service manifests — they are NOT interpolated in .tfvars.json or any Terraform variable files. If azure-prepare generated a main.tfvars.json with Go-style template expressions, those literal strings are passed to Terraform.

Solution:

  1. Fix the syntax in infra/main.tfvars.json — replace Go-style {{ .Env.* }} with ${VAR}:

    {
        "environment_name": "${AZURE_ENV_NAME}",
        "location": "${AZURE_LOCATION}",
        "subscription_id": "${AZURE_SUBSCRIPTION_ID}"
    }
  2. Or use TF_VAR_* environment variables if you don't have main.tfvars.json:

    azd env set TF_VAR_environment_name "$(azd env get-value AZURE_ENV_NAME)"
    azd env set TF_VAR_location "$(azd env get-value AZURE_LOCATION)"
    azd env set TF_VAR_subscription_id "$(azd env get-value AZURE_SUBSCRIPTION_ID)"
  3. Ensure variables.tf declares all required variables:

    variable "environment_name" { type = string }
    variable "location" { type = string }
  4. Re-run deployment:

    azd up --no-prompt

⚠️ Prevention: This issue should be caught by azure-validate Step 10 (Template Variable Resolution Check) before deployment. If you encounter it, re-run validation after fixing.

Retry

After fixing the issue:

azd up --no-prompt

Principal Type Mismatch

Symptom: azd up fails during provisioning with:

PrincipalId '...' has type 'ServicePrincipal', which is different from specified PrincipalType 'User'

Cause: Many AZD templates (e.g., functions-quickstart-python-http-azd) include RBAC role assignments for the deploying user with hardcoded principalType: 'User'. This is controlled by an allowUserIdentityPrincipal flag in main.bicep's storageEndpointConfig variable. When deploying from CI/CD with a service principal, azd sets AZURE_PRINCIPAL_ID to that service principal's object ID, but the Bicep still tries to create a role assignment with principalType: 'User', causing ARM to reject it.

Solution:

In infra/main.bicep, find the storageEndpointConfig variable and set allowUserIdentityPrincipal to false:

var storageEndpointConfig = {
  enableBlob: true
  enableQueue: false
  enableTable: false
  enableFiles: false
  allowUserIdentityPrincipal: false  // Set to false for service principal deployments
}

⚠️ Do NOT try to fix this by running azd env set AZURE_PRINCIPAL_ID "". The azd CLI repopulates this value from the current auth context, so clearing it has no effect.

Cleanup (DESTRUCTIVE)

azd down --force --purge

⚠️ Permanently deletes ALL resources including databases and Key Vaults.

Source: SKILL.md on GitHub

2 warnings15d4 checks · Risk SAFE
  • Gen Agent Trust Hub15d

    This skill provides a robust framework for executing Azure deployments using various infrastructure-as-code tools. It includes several security considerations such as remote script installation and command execution, which are essential for its deployment functionality and are managed through strict prerequisite checks and user confirmation rules.

  • Socket15d

    1 alert: gptAnomaly

  • Snyk15d

    Risk: LOW · No issues

  • Runlayer7mo

    30/31 files flagged

Signed by skilld at b3c238e. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 2 months ago
metadata
{
  "author": "Microsoft",
  "version": "1.2.1"
}

README badge

README badge for microsoft/skills/azure-deploy