{
  "schema": "https://ai-atoms.com/schemas/skill-v1.json",
  "type": "skill",
  "id": "skill/azd-deployment",
  "version": "1.0.0",
  "name": "Azd Deployment",
  "description": "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 Cont...",
  "system_prompt_fragment": "# Azure Developer CLI (azd) Container Apps Deployment\n\nDeploy containerized frontend + backend applications to Azure Container Apps with remote builds, managed identity, and idempotent infrastructure.\n\n## Quick Start\n\n```bash\n# Initialize and deploy\nazd auth login\nazd init                    # Creates azure.yaml and .azure/ folder\nazd env new <env-name>      # Create environment (dev, staging, prod)\nazd up                      # Provision infra + build + deploy\n```\n\n## Core File Structure\n\n```\nproject/\n├── azure.yaml              # azd service definitions + hooks\n├── infra/\n│   ├── main.bicep          # Root infrastructure module\n│   ├── main.parameters.json # Parameter injection from env vars\n│   └── modules/\n│       ├── container-apps-environment.bicep\n│       └── container-app.bicep\n├── .azure/\n│   ├── config.json         # Default environment pointer\n│   └── <env-name>/\n│       ├── .env            # Environment-specific values (azd-managed)\n│       └── config.json     # Environment metadata\n└── src/\n    ├── frontend/Dockerfile\n    └── backend/Dockerfile\n```\n\n## azure.yaml Configuration\n\n### Minimal Configuration\n\n```yaml\nname: azd-deployment\nservices:\n  backend:\n    project: ./src/backend\n    language: python\n    host: containerapp\n    docker:\n      path: ./Dockerfile\n      remoteBuild: true\n```\n\n### Full Configuration with Hooks\n\n```yaml\nname: azd-deployment\nmetadata:\n  template: my-project@1.0.0\n\ninfra:\n  provider: bicep\n  path: ./infra\n\nazure:\n  location: eastus2\n\nservices:\n  frontend:\n    project: ./src/frontend\n    language: ts\n    host: containerapp\n    docker:\n      path: ./Dockerfile\n      context: .\n      remoteBuild: true\n\n  backend:\n    project: ./src/backend\n    language: python\n    host: containerapp\n    docker:\n      path: ./Dockerfile\n      context: .\n      remoteBuild: true\n\nhooks:\n  preprovision:\n    shell: sh\n    run: |\n      echo \"Before provisioning...\"\n      \n  postprovision:\n    shell: sh\n    run: |\n      echo \"After provisioning - set up RBAC, etc.\"\n      \n  postdeploy:\n    shell: sh\n    run: |\n      echo \"Frontend: ${SERVICE_FRONTEND_URI}\"\n      echo \"Backend: ${SERVICE_BACKEND_URI}\"\n```\n\n### Key azure.yaml Options\n\n| Option | Description |\n|--------|-------------|\n| `remoteBuild: true` | Build images in Azure Container Registry (recommended) |\n| `context: .` | Docker build context relative to project path |\n| `host: containerapp` | Deploy to Azure Container Apps |\n| `infra.provider: bicep` | Use Bicep for infrastructure |\n\n## Environment Variables Flow\n\n### Three-Level Configuration\n\n1. **Local `.env`** - For local development only\n2. **`.azure/<env>/.env`** - azd-managed, auto-populated from Bicep outputs\n3. **`main.parameters.json`** - Maps env vars to Bicep parameters\n\n### Parameter Injection Pattern\n\n```json\n// infra/main.parameters.json\n{\n  \"parameters\": {\n    \"environmentName\": { \"value\": \"${AZURE_ENV_NAME}\" },\n    \"location\": { \"value\": \"${AZURE_LOCATION=eastus2}\" },\n    \"azureOpenAiEndpoint\": { \"value\": \"${AZURE_OPENAI_ENDPOINT}\" }\n  }\n}\n```\n\nSyntax: `${VAR_NAME}` or `${VAR_NAME=default_value}`\n\n### Setting Environment Variables\n\n```bash\n# Set for current environment\nazd env set AZURE_OPENAI_ENDPOINT \"https://my-openai.openai.azure.com\"\nazd env set AZURE_SEARCH_ENDPOINT \"https://my-search.search.windows.net\"\n\n# Set during init\nazd env new prod\nazd env set AZURE_OPENAI_ENDPOINT \"...\" \n```\n\n### Bicep Output → Environment Variable\n\n```bicep\n// In main.bicep - outputs auto-populate .azure/<env>/.env\noutput SERVICE_FRONTEND_URI string = frontend.outputs.uri\noutput SERVICE_BACKEND_URI string = backend.outputs.uri\noutput BACKEND_PRINCIPAL_ID string = backend.outputs.principalId\n```\n\n## Idempotent Deployments\n\n### Why azd up is Idempotent\n\n1. **Bicep is declarative** - Resources reconcile to desired state\n2. **Remote builds tag uniquely** - Image tags include deployment timestamp\n3. **ACR reuses layers** - Only changed layers upload\n\n### Preserving Manual Changes\n\nCustom domains added via Portal can be lost on redeploy. Preserve with hooks:\n\n```yaml\nhooks:\n  preprovision:\n    shell: sh\n    run: |\n      # Save custom domains before provision\n      if az containerapp show --name \"$FRONTEND_NAME\" -g \"$RG\" &>/dev/null; then\n        az containerapp show --name \"$FRONTEND_NAME\" -g \"$RG\" \\\n          --query \"properties.configuration.ingress.customDomains\" \\\n          -o json > /tmp/domains.json\n      fi\n\n  postprovision:\n    shell: sh\n    run: |\n      # Verify/restore custom domains\n      if [ -f /tmp/domains.json ]; then\n        echo \"Saved domains: $(cat /tmp/domains.json)\"\n      fi\n```\n\n### Handling Existing Resources\n\n```bicep\n// Reference existing ACR (don't recreate)\nresource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-07-01' existing = {\n  name: containerRegistryName\n}\n\n// Set customDomains to null to preserve Portal-added domains\ncustomDomains: empty(customDomainsParam) ? null : customDomainsParam\n```\n\n## Container App Service Discovery\n\nInternal HTTP routing between Container Apps in same environment:\n\n```bicep\n// Backend reference in frontend env vars\nenv: [\n  {\n    name: 'BACKEND_URL'\n    value: 'http://ca-backend-${resourceToken}'  // Internal DNS\n  }\n]\n```\n\nFrontend nginx proxies to internal URL:\n```nginx\nlocation /api {\n    proxy_pass $BACKEND_URL;\n}\n```\n\n## Managed Identity & RBAC\n\n### Enable System-Assigned Identity\n\n```bicep\nresource containerApp 'Microsoft.App/containerApps@2024-03-01' = {\n  identity: {\n    type: 'SystemAssigned'\n  }\n}\n\noutput principalId string = containerApp.identity.principalId\n```\n\n### Post-Provision RBAC Assignment\n\n```yaml\nhooks:\n  postprovision:\n    shell: sh\n    run: |\n      PRINCIPAL_ID=\"${BACKEND_PRINCIPAL_ID}\"\n      \n      # Azure OpenAI access\n      az role assignment create \\\n        --assignee-object-id \"$PRINCIPAL_ID\" \\\n        --assignee-principal-type ServicePrincipal \\\n        --role \"Cognitive Services OpenAI User\" \\\n        --scope \"$OPENAI_RESOURCE_ID\" 2>/dev/null || true\n      \n      # Azure AI Search access\n      az role assignment create \\\n        --assignee-object-id \"$PRINCIPAL_ID\" \\\n        --role \"Search Index Data Reader\" \\\n        --scope \"$SEARCH_RESOURCE_ID\" 2>/dev/null || true\n```\n\n## Common Commands\n\n```bash\n# Environment management\nazd env list                        # List environments\nazd env select <name>               # Switch environment\nazd env get-values                  # Show all env vars\nazd env set KEY value               # Set variable\n\n# Deployment\nazd up                              # Full provision + deploy\nazd provision                       # Infrastructure only\nazd deploy                          # Code deployment only\nazd deploy --service backend        # Deploy single service\n\n# Debugging\nazd show                            # Show project status\naz containerapp logs show -n <app> -g <rg> --follow  # Stream logs\n```\n\n## Reference Files\n\n- **Bicep patterns**: See references/bicep-patterns.md for Container Apps modules\n- **Troubleshooting**: See references/troubleshooting.md for common issues\n- **azure.yaml schema**: See references/azure-yaml-schema.md for full options\n\n## Critical Reminders\n\n1. **Always use `remoteBuild: true`** - Local builds fail on M1/ARM Macs deploying to AMD64\n2. **Bicep outputs auto-populate .azure/<env>/.env** - Don't manually edit\n3. **Use `azd env set` for secrets** - Not main.parameters.json defaults\n4. **Service tags (`azd-service-name`)** - Required for azd to find Container Apps\n5. **`|| true` in hooks** - Prevent RBAC \"already exists\" errors from failing deploy\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.",
  "applicable_domains": [
    "devops"
  ],
  "category": "devops",
  "invocation": [
    "/azd-deployment"
  ],
  "authored_by": "claudeskills.in community",
  "source_url": "https://claudeskills.in/skill/azd-deployment",
  "provenance": {
    "source": "claudeskills.in",
    "source_url": "https://claudeskills.in/skill/azd-deployment",
    "license": "unknown",
    "imported_at": "2026-09-03",
    "notes": "Aggregated by claudeskills.in from community GitHub lists."
  },
  "tags": [
    "claudeskills",
    "devops"
  ],
  "lifecycle": "draft"
}