4. 容器应用定义与部署
把应用真正跑在 Azure 容器应用(Azure Container Apps,ACA)上,核心链路只有四步:镜像构建 → 镜像入库 → 应用定义 → 部署与验证。本节以一条可复现的路径,把 Dockerfile、Azure CLI、Bicep、Terraform 和 GitHub Actions 串起来,完成一次从本地代码到 ACA 上可访问应用的首次部署。
一、Dockerfile:把应用固化成可移植镜像
ACA 只接受容器镜像,因此第一步是让应用具备可构建的 Dockerfile。以 Node.js 服务为例,采用多阶段构建可以显著减小镜像体积并降低攻击面:
# 构建阶段
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
# 运行阶段
FROM node:20-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app ./
EXPOSE 3000
CMD ["node", "server.js"]
关键约定有三点:监听端口必须与后续 ACA 的 targetPort 一致(示例为 3000);进程必须前台运行,不能后台化,否则容器会被判定为退出;镜像标签不要只用 latest,建议使用 Git 短 SHA,例如 myacr.azurecr.io/orders-api:1a2b3c4,便于回滚与追踪。
二、镜像入库:ACR 与身份认证
镜像需要推送到 Azure 容器注册表(ACR)。首次部署时,先创建注册表并登录:
az acr create -g rg-aca-demo -n myacrdemo --sku Basic
az acr login -n myacrdemo
docker build -t myacrdemo.azurecr.io/orders-api:1a2b3c4 .
docker push myacrdemo.azurecr.io/orders-api:1a2b3c4
ACA 拉取镜像时不应使用管理员密码,而应通过托管标识 + AcrPull 角色授权。这是生产环境的基本要求,也是后续 Bicep/Terraform 中必须体现的配置项。
三、应用定义:环境、修订与入口
ACA 的资源模型分三层:环境(Environment)提供共享的网络与日志底座;容器应用(Container App)承载应用定义;修订(Revision)是每次变更产生的不可变快照。首次部署时,需要明确以下参数:
- ingress:是否启用外部入口、目标端口、传输协议(http/https)。
- resources:CPU 与内存,例如 0.5 vCPU / 1 GiB。
- scale:最小/最大副本数,示例
minReplicas=0, maxReplicas=3,可缩容到零以节省成本。 - registry:镜像地址与托管标识凭据。
- env:环境变量,敏感值应引用 Key Vault 或 ACA Secret。
下图展示了从代码到 ACA 应用的完整链路,以及各工具在链路中的位置:
四、Azure CLI:最快完成首次部署
CLI 适合验证链路是否通畅。以下命令创建环境并部署应用,注意 --target-port 与 Dockerfile 的 3000 保持一致:
az containerapp env create -g rg-aca-demo -n aca-env-demo --location eastasia
az containerapp create -g rg-aca-demo -n orders-api \
--environment aca-env-demo \
--image myacrdemo.azurecr.io/orders-api:1a2b3c4 \
--registry-server myacrdemo.azurecr.io \
--target-port 3000 --ingress external \
--cpu 0.5 --memory 1Gi \
--min-replicas 0 --max-replicas 3
执行后可用 az containerapp show -n orders-api -g rg-aca-demo --query properties.configuration.ingress.fqdn -o tsv 获取访问地址。若返回 provisioningState: Failed,优先检查镜像标签是否存在、托管标识是否具备 AcrPull 权限、目标端口是否与容器监听端口一致。
五、Bicep 与 Terraform:把定义变成可复用资产
CLI 命令难以版本化,声明式工具更适合规模化。Bicep 直接编译为 ARM 模板,与 Azure 资源模型贴合;Terraform 则适合已有 HCL 工作流的团队。两者都需要显式声明环境、应用、注册表凭据与缩放规则。以 Bicep 为例,核心资源片段如下:
resource app 'Microsoft.App/containerApps@2024-03-01' = {
name: 'orders-api'
location: location
properties: {
environmentId: env.id
configuration: {
ingress: { external: true, targetPort: 3000 }
registries: [{
server: 'myacrdemo.azurecr.io'
identity: managedIdentity.id
}]
}
template: {
containers: [{
name: 'orders-api'
image: 'myacrdemo.azurecr.io/orders-api:1a2b3c4'
resources: { cpu: json('0.5'), memory: '1Gi' }
}]
scale: { minReplicas: 0, maxReplicas: 3 }
}
}
}
Terraform 中对应使用 azurerm_container_app 资源,字段语义基本一致,差异主要在引用方式与状态管理。选择建议:纯 Azure 团队优先 Bicep,已有 Terraform 体系则保持一致,不要在同一环境混用两套状态源。
六、GitHub Actions:把首次部署变成可重复流水线
CI/CD 的目标是让每次提交自动产出新修订。推荐使用 OIDC 联合凭据登录 Azure,避免在仓库中存放长期密钥。工作流关键步骤:
- uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- run: |
az acr build -r myacrdemo -t orders-api:${{ github.sha }} .
az containerapp update -n orders-api -g rg-aca-demo \
--image myacrdemo.azurecr.io/orders-api:${{ github.sha }}
使用 az acr build 可在云端构建,无需在 Runner 上安装 Docker。az containerapp update 会生成新修订,配合单修订模式或流量拆分即可实现灰度发布。
latest 导致无法追踪;未授予 AcrPull 导致镜像拉取失败;targetPort 与容器监听端口不一致导致健康检查失败;minReplicas=0 时首次请求会有冷启动延迟,需在验收时纳入预期。完成首次部署后,判断成功的标准不是命令返回 0,而是:provisioningState 为 Succeeded、FQDN 可访问且健康检查返回 200、修订记录与预期镜像标签一致、日志中无拉取或端口错误。这四点同时满足,才说明从 Dockerfile 到 ACA 应用的链路真正闭环。