azd-deployment

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Azure Developer CLI (azd) Container Apps Deployment

Azure Developer CLI (azd) Container Apps 部署

Deploy containerized frontend + backend applications to Azure Container Apps with remote builds, managed identity, and idempotent infrastructure.
通过远程构建、托管标识和幂等基础设施,将容器化的前端+后端应用部署到Azure Container Apps。

Quick Start

快速开始

bash
undefined
bash
undefined

Initialize and deploy

初始化并部署

azd auth login azd init # Creates azure.yaml and .azure/ folder azd env new <env-name> # Create environment (dev, staging, prod) azd up # Provision infra + build + deploy
undefined
azd auth login azd init # 创建azure.yaml和.azure/文件夹 azd env new <env-name> # 创建环境(dev、staging、prod) azd up # 预置基础设施 + 构建 + 部署
undefined

Core File Structure

核心文件结构

project/
├── azure.yaml              # azd service definitions + hooks
├── infra/
│   ├── main.bicep          # Root infrastructure module
│   ├── main.parameters.json # Parameter injection from env vars
│   └── modules/
│       ├── container-apps-environment.bicep
│       └── container-app.bicep
├── .azure/
│   ├── config.json         # Default environment pointer
│   └── <env-name>/
│       ├── .env            # Environment-specific values (azd-managed)
│       └── config.json     # Environment metadata
└── src/
    ├── frontend/Dockerfile
    └── backend/Dockerfile
project/
├── azure.yaml              # azd服务定义 + 钩子
├── infra/
│   ├── main.bicep          # 根基础设施模块
│   ├── main.parameters.json # 从环境变量注入参数
│   └── modules/
│       ├── container-apps-environment.bicep
│       └── container-app.bicep
├── .azure/
│   ├── config.json         # 默认环境指针
│   └── <env-name>/
│       ├── .env            # 环境专属值(由azd管理)
│       └── config.json     # 环境元数据
└── src/
    ├── frontend/Dockerfile
    └── backend/Dockerfile

azure.yaml Configuration

azure.yaml 配置

Minimal Configuration

最简配置

yaml
name: azd-deployment
services:
  backend:
    project: ./src/backend
    language: python
    host: containerapp
    docker:
      path: ./Dockerfile
      remoteBuild: true
yaml
name: azd-deployment
services:
  backend:
    project: ./src/backend
    language: python
    host: containerapp
    docker:
      path: ./Dockerfile
      remoteBuild: true

Full Configuration with Hooks

带钩子的完整配置

yaml
name: azd-deployment
metadata:
  template: my-project@1.0.0

infra:
  provider: bicep
  path: ./infra

azure:
  location: eastus2

services:
  frontend:
    project: ./src/frontend
    language: ts
    host: containerapp
    docker:
      path: ./Dockerfile
      context: .
      remoteBuild: true

  backend:
    project: ./src/backend
    language: python
    host: containerapp
    docker:
      path: ./Dockerfile
      context: .
      remoteBuild: true

hooks:
  preprovision:
    shell: sh
    run: |
      echo "Before provisioning..."
      
  postprovision:
    shell: sh
    run: |
      echo "After provisioning - set up RBAC, etc."
      
  postdeploy:
    shell: sh
    run: |
      echo "Frontend: ${SERVICE_FRONTEND_URI}"
      echo "Backend: ${SERVICE_BACKEND_URI}"
yaml
name: azd-deployment
metadata:
  template: my-project@1.0.0

infra:
  provider: bicep
  path: ./infra

azure:
  location: eastus2

services:
  frontend:
    project: ./src/frontend
    language: ts
    host: containerapp
    docker:
      path: ./Dockerfile
      context: .
      remoteBuild: true

  backend:
    project: ./src/backend
    language: python
    host: containerapp
    docker:
      path: ./Dockerfile
      context: .
      remoteBuild: true

hooks:
  preprovision:
    shell: sh
    run: |
      echo "Before provisioning..."
      
  postprovision:
    shell: sh
    run: |
      echo "After provisioning - set up RBAC, etc."
      
  postdeploy:
    shell: sh
    run: |
      echo "Frontend: ${SERVICE_FRONTEND_URI}"
      echo "Backend: ${SERVICE_BACKEND_URI}"

Key azure.yaml Options

azure.yaml 关键选项

OptionDescription
remoteBuild: true
Build images in Azure Container Registry (recommended)
context: .
Docker build context relative to project path
host: containerapp
Deploy to Azure Container Apps
infra.provider: bicep
Use Bicep for infrastructure
选项描述
remoteBuild: true
在Azure Container Registry中构建镜像(推荐)
context: .
相对于项目路径的Docker构建上下文
host: containerapp
部署到Azure Container Apps
infra.provider: bicep
使用Bicep管理基础设施

Environment Variables Flow

环境变量流转

Three-Level Configuration

三级配置

  1. Local
    .env
    - For local development only
  2. .azure/<env>/.env
    - azd-managed, auto-populated from Bicep outputs
  3. main.parameters.json
    - Maps env vars to Bicep parameters
  1. 本地
    .env
    - 仅用于本地开发
  2. .azure/<env>/.env
    - 由azd管理,从Bicep输出自动填充
  3. main.parameters.json
    - 将环境变量映射到Bicep参数

Parameter Injection Pattern

参数注入模式

json
// infra/main.parameters.json
{
  "parameters": {
    "environmentName": { "value": "${AZURE_ENV_NAME}" },
    "location": { "value": "${AZURE_LOCATION=eastus2}" },
    "azureOpenAiEndpoint": { "value": "${AZURE_OPENAI_ENDPOINT}" }
  }
}
Syntax:
${VAR_NAME}
or
${VAR_NAME=default_value}
json
// infra/main.parameters.json
{
  "parameters": {
    "environmentName": { "value": "${AZURE_ENV_NAME}" },
    "location": { "value": "${AZURE_LOCATION=eastus2}" },
    "azureOpenAiEndpoint": { "value": "${AZURE_OPENAI_ENDPOINT}" }
  }
}
语法:
${VAR_NAME}
${VAR_NAME=default_value}

Setting Environment Variables

设置环境变量

bash
undefined
bash
undefined

Set for current environment

为当前环境设置

azd env set AZURE_OPENAI_ENDPOINT "https://my-openai.openai.azure.com" azd env set AZURE_SEARCH_ENDPOINT "https://my-search.search.windows.net"
azd env set AZURE_OPENAI_ENDPOINT "https://my-openai.openai.azure.com" azd env set AZURE_SEARCH_ENDPOINT "https://my-search.search.windows.net"

Set during init

在初始化时设置

azd env new prod azd env set AZURE_OPENAI_ENDPOINT "..."
undefined
azd env new prod azd env set AZURE_OPENAI_ENDPOINT "..."
undefined

Bicep Output → Environment Variable

Bicep 输出 → 环境变量

bicep
// In main.bicep - outputs auto-populate .azure/<env>/.env
output SERVICE_FRONTEND_URI string = frontend.outputs.uri
output SERVICE_BACKEND_URI string = backend.outputs.uri
output BACKEND_PRINCIPAL_ID string = backend.outputs.principalId
bicep
// 在main.bicep中 - 输出会自动填充.azure/<env>/.env
output SERVICE_FRONTEND_URI string = frontend.outputs.uri
output SERVICE_BACKEND_URI string = backend.outputs.uri
output BACKEND_PRINCIPAL_ID string = backend.outputs.principalId

Idempotent Deployments

幂等部署

Why azd up is Idempotent

为什么azd up是幂等的

  1. Bicep is declarative - Resources reconcile to desired state
  2. Remote builds tag uniquely - Image tags include deployment timestamp
  3. ACR reuses layers - Only changed layers upload
  1. Bicep是声明式的 - 资源会协调至期望状态
  2. 远程构建生成唯一标签 - 镜像标签包含部署时间戳
  3. ACR复用镜像层 - 仅上传变更的层

Preserving Manual Changes

保留手动修改

Custom domains added via Portal can be lost on redeploy. Preserve with hooks:
yaml
hooks:
  preprovision:
    shell: sh
    run: |
      # Save custom domains before provision
      if az containerapp show --name "$FRONTEND_NAME" -g "$RG" &>/dev/null; then
        az containerapp show --name "$FRONTEND_NAME" -g "$RG" \
          --query "properties.configuration.ingress.customDomains" \
          -o json > /tmp/domains.json
      fi

  postprovision:
    shell: sh
    run: |
      # Verify/restore custom domains
      if [ -f /tmp/domains.json ]; then
        echo "Saved domains: $(cat /tmp/domains.json)"
      fi
通过门户添加的自定义域名可能在重新部署时丢失,可通过钩子保留:
yaml
hooks:
  preprovision:
    shell: sh
    run: |
      # 预置前保存自定义域名
      if az containerapp show --name "$FRONTEND_NAME" -g "$RG" &>/dev/null; then
        az containerapp show --name "$FRONTEND_NAME" -g "$RG" \
          --query "properties.configuration.ingress.customDomains" \
          -o json > /tmp/domains.json
      fi

  postprovision:
    shell: sh
    run: |
      # 验证/恢复自定义域名
      if [ -f /tmp/domains.json ]; then
        echo "Saved domains: $(cat /tmp/domains.json)"
      fi

Handling Existing Resources

处理现有资源

bicep
// Reference existing ACR (don't recreate)
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-07-01' existing = {
  name: containerRegistryName
}

// Set customDomains to null to preserve Portal-added domains
customDomains: empty(customDomainsParam) ? null : customDomainsParam
bicep
// 引用现有ACR(不重新创建)
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-07-01' existing = {
  name: containerRegistryName
}

// 将customDomains设为null以保留门户添加的域名
customDomains: empty(customDomainsParam) ? null : customDomainsParam

Container App Service Discovery

Container App 服务发现

Internal HTTP routing between Container Apps in same environment:
bicep
// Backend reference in frontend env vars
env: [
  {
    name: 'BACKEND_URL'
    value: 'http://ca-backend-${resourceToken}'  // Internal DNS
  }
]
Frontend nginx proxies to internal URL:
nginx
location /api {
    proxy_pass $BACKEND_URL;
}
同一环境中Container Apps之间的内部HTTP路由:
bicep
// 前端环境变量中的后端引用
env: [
  {
    name: 'BACKEND_URL'
    value: 'http://ca-backend-${resourceToken}'  // 内部DNS
  }
]
前端nginx代理到内部URL:
nginx
location /api {
    proxy_pass $BACKEND_URL;
}

Managed Identity & RBAC

托管标识与RBAC

Enable System-Assigned Identity

启用系统分配的标识

bicep
resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  identity: {
    type: 'SystemAssigned'
  }
}

output principalId string = containerApp.identity.principalId
bicep
resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  identity: {
    type: 'SystemAssigned'
  }
}

output principalId string = containerApp.identity.principalId

Post-Provision RBAC Assignment

预置后RBAC分配

yaml
hooks:
  postprovision:
    shell: sh
    run: |
      PRINCIPAL_ID="${BACKEND_PRINCIPAL_ID}"
      
      # Azure OpenAI access
      az role assignment create \
        --assignee-object-id "$PRINCIPAL_ID" \
        --assignee-principal-type ServicePrincipal \
        --role "Cognitive Services OpenAI User" \
        --scope "$OPENAI_RESOURCE_ID" 2>/dev/null || true
      
      # Azure AI Search access
      az role assignment create \
        --assignee-object-id "$PRINCIPAL_ID" \
        --role "Search Index Data Reader" \
        --scope "$SEARCH_RESOURCE_ID" 2>/dev/null || true
yaml
hooks:
  postprovision:
    shell: sh
    run: |
      PRINCIPAL_ID="${BACKEND_PRINCIPAL_ID}"
      
      # Azure OpenAI 访问权限
      az role assignment create \
        --assignee-object-id "$PRINCIPAL_ID" \
        --assignee-principal-type ServicePrincipal \
        --role "Cognitive Services OpenAI User" \
        --scope "$OPENAI_RESOURCE_ID" 2>/dev/null || true
      
      # Azure AI Search 访问权限
      az role assignment create \
        --assignee-object-id "$PRINCIPAL_ID" \
        --role "Search Index Data Reader" \
        --scope "$SEARCH_RESOURCE_ID" 2>/dev/null || true

Common Commands

常用命令

bash
undefined
bash
undefined

Environment management

环境管理

azd env list # List environments azd env select <name> # Switch environment azd env get-values # Show all env vars azd env set KEY value # Set variable
azd env list # 列出环境 azd env select <name> # 切换环境 azd env get-values # 显示所有环境变量 azd env set KEY value # 设置变量

Deployment

部署

azd up # Full provision + deploy azd provision # Infrastructure only azd deploy # Code deployment only azd deploy --service backend # Deploy single service
azd up # 完整预置 + 部署 azd provision # 仅基础设施 azd deploy # 仅代码部署 azd deploy --service backend # 部署单个服务

Debugging

调试

azd show # Show project status az containerapp logs show -n <app> -g <rg> --follow # Stream logs
undefined
azd show # 显示项目状态 az containerapp logs show -n <app> -g <rg> --follow # 流式查看日志
undefined

Reference Files

参考文件

  • Bicep patterns: See references/bicep-patterns.md for Container Apps modules
  • Troubleshooting: See references/troubleshooting.md for common issues
  • azure.yaml schema: See references/azure-yaml-schema.md for full options
  • Bicep 模式: 查看 references/bicep-patterns.md 获取Container Apps模块
  • 故障排查: 查看 references/troubleshooting.md 解决常见问题
  • azure.yaml schema: 查看 references/azure-yaml-schema.md 获取完整选项

Critical Reminders

重要提醒

  1. Always use
    remoteBuild: true
    - Local builds fail on M1/ARM Macs deploying to AMD64
  2. Bicep outputs auto-populate .azure/<env>/.env - Don't manually edit
  3. Use
    azd env set
    for secrets
    - Not main.parameters.json defaults
  4. Service tags (
    azd-service-name
    )
    - Required for azd to find Container Apps
  5. || true
    in hooks
    - Prevent RBAC "already exists" errors from failing deploy
  1. 始终使用
    remoteBuild: true
    - M1/ARM Mac的本地构建部署到AMD64时会失败
  2. Bicep输出自动填充.azure/<env>/.env - 请勿手动编辑
  3. 使用
    azd env set
    设置密钥
    - 不要在main.parameters.json中设置默认值
  4. 服务标签 (
    azd-service-name
    )
    - azd查找Container Apps必需
  5. 钩子中的
    || true
    - 防止RBAC“已存在”错误导致部署失败