何时使用
适用于用 Azure Developer CLI(azd) 把容器化的「前端 + 后端」应用部署到 Azure Container Apps(ACA),并满足以下任一诉求时:
- 一条
azd up完成「基础设施供给 + 镜像构建 + 部署」,且可反复执行(幂等)。 - 用 Bicep 声明式管理 ACA 环境、容器应用、ACR,并把 Bicep 输出回灌环境变量。
- 在 ACR 远程构建镜像(
remoteBuild: true),避免本地架构差异。 - 启用系统分配托管身份(Managed Identity),并在 provision 后自动配 RBAC(如访问 Azure OpenAI / AI Search)。
- 配置同环境内 Container Apps 之间的内部服务发现(internal DNS)。
不该用边界:
- AWS 无服务器(Lambda/API Gateway/SAM)→ 用
aws-serverless-builder;GCP 无服务器 → 用gcp-cloud-run。 - 需要 Kubernetes 原生编排(AKS、Helm、节点池)而非托管 ACA → 不在范围。
- 仅做 Azure 整体架构选型 / 成本与安全评审(不落到 azd 部署)→ 用
azure-cloud-architect。 - 纯应用代码开发、纯 Dockerfile 优化(不涉及 azd/ACA 部署链路)→ 用
docker-container-optimizer。 - 不替代环境内的实际验证、测试与专家评审;缺少所需输入、权限、安全边界或成功标准时先停下澄清。
核心原则:镜像走 ACR 远程构建;基础设施用 Bicep 保持声明式与幂等;密钥用 azd env set 注入而非写进 main.parameters.json 默认值;Bicep 输出自动回灌 .azure/<env>/.env,勿手改。
步骤 / 指令
- 登录与初始化:
azd auth login→azd init(生成azure.yaml与.azure/)→azd env new <env>(dev/staging/prod)。 - 定义服务:在
azure.yaml为每个服务声明host: containerapp与docker.remoteBuild: true,指定project/language/docker.path/context。 - 写基础设施:
infra/main.bicep(根模块)+infra/modules/(ACA 环境、容器应用),infra/main.parameters.json把环境变量映射到 Bicep 参数。 - 注入配置/密钥:
azd env set KEY value设当前环境变量;Bicepoutput自动回灌.azure/<env>/.env(如服务 URI、principalId)。 - 托管身份与 RBAC:容器应用启用
SystemAssigned身份并output principalId;在postprovision钩子里用az role assignment create(末尾|| true防「已存在」报错)授角色。 - 部署:
azd up一次完成 provision + build + deploy;增量时azd deploy --service <name>只部署单服务。 - 校验与排障:
azd show看状态,az containerapp logs show -n <app> -g <rg> --follow流式查日志。
文件结构骨架:
project/
├── azure.yaml # azd 服务定义 + hooks
├── infra/
│ ├── main.bicep # 根基础设施模块
│ ├── main.parameters.json # 环境变量 → Bicep 参数注入
│ └── modules/
│ ├── container-apps-environment.bicep
│ └── container-app.bicep
├── .azure/
│ ├── config.json # 默认环境指针
│ └── <env-name>/.env # azd 托管,自动回灌(勿手改)
└── src/{frontend,backend}/Dockerfile
常用命令:
# 环境管理
azd env list # 列出环境
azd env select <name> # 切换环境
azd env get-values # 查看全部环境变量
azd env set KEY value # 设置变量(推荐用于密钥)
# 部署
azd up # 全量 provision + build + deploy
azd provision # 仅基础设施
azd deploy # 仅代码部署
azd deploy --service backend # 仅部署单个服务
# 排障
azd show
az containerapp logs show -n <app> -g <rg> --follow
示例
azure.yaml(前后端 + 钩子,均启用远程构建):
name: azure-container-apps-deploy
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:
postdeploy:
shell: sh
run: |
echo "Frontend: ${SERVICE_FRONTEND_URI}"
echo "Backend: ${SERVICE_BACKEND_URI}"
参数注入与 Bicep 输出回灌:
// infra/main.parameters.json — 语法 ${VAR} 或 ${VAR=default}
{ "parameters": {
"environmentName": { "value": "${AZURE_ENV_NAME}" },
"location": { "value": "${AZURE_LOCATION=eastus2}" },
"azureOpenAiEndpoint": { "value": "${AZURE_OPENAI_ENDPOINT}" }
}}
// main.bicep —— output 自动回灌 .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
托管身份 + postprovision RBAC(|| true 防重复授权失败):
resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
identity: { type: 'SystemAssigned' }
}
output principalId string = containerApp.identity.principalId
hooks:
postprovision:
shell: sh
run: |
PRINCIPAL_ID="${BACKEND_PRINCIPAL_ID}"
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
服务发现(同环境内部 DNS 路由)+ 复用既有 ACR:
// 前端环境变量引用后端内部地址
env: [ { name: 'BACKEND_URL', value: 'http://ca-backend-${resourceToken}' } ]
// 引用已存在的 ACR,不重建
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-07-01' existing = {
name: containerRegistryName
}
// 保留 Portal 手动添加的自定义域名:为空则置 null
customDomains: empty(customDomainsParam) ? null : customDomainsParam
注意事项
- 始终用
remoteBuild: true(HIGH):本地在 M1/ARM Mac 上构建会因目标 AMD64 架构而失败;在 ACR 远程构建可避免架构错配,并按层复用、只上传变更层。 - Bicep 输出自动回灌
.azure/<env>/.env,勿手改:手动编辑会被下次azd up覆盖;要改值用azd env set。 - 密钥用
azd env set而非参数默认值:不要把 secret 写进main.parameters.json默认值或提交进仓库。 - 服务标签
azd-service-name必需:缺失则 azd 找不到对应的 Container App,部署/更新会失配。 - 钩子里 RBAC 加
|| true:角色「已存在」会让az role assignment create非零退出,进而中断部署;幂等容错很关键。 - 保护 Portal 手动改动:经 Portal 添加的自定义域名可能在重部署时丢失。用
preprovision钩子先az containerapp show ... --query customDomains导出备份,postprovision校验/恢复;Bicep 里把customDomains在无入参时置null以保留既有域名。 - 幂等来自三处:Bicep 声明式(资源收敛到目标态)+ 远程构建唯一标签(含部署时间戳)+ ACR 层复用。
互见
- related:
azure-cloud-architect—— 先做 Azure 架构选型/Bicep 设计/成本安全评审,再落到 azd 部署 - related:
gcp-cloud-run—— GCP 侧等价的容器化无服务器部署 - related:
aws-serverless-builder—— AWS 侧无服务器部署对照 - combines_with:
docker-container-optimizer—— 优化 Dockerfile 与镜像层,配合远程构建 - combines_with:
terraform-specialist—— 用 Terraform 替代/补充 Bicep 管理周边基础设施 - combines_with:
github-actions-author—— 在 CI/CD 流水线中编排azd provision/azd deploy
采编自 sickn33/antigravity-awesome-skills(MIT)。