Azure App Service使用托管身份无法访问ACR的问题求助
Azure App Service多容器部署ACR镜像认证失败问题
问题概述
我在Azure App Service上部署多容器环境,使用存储在Azure Container Registry (ACR)中的镜像。已为App Service和ACR配置托管身份,并为App Service的托管身份分配了ACR Pull角色。可通过Azure CLI连接注册表,流水线也能正常推送镜像,但App Service拉取镜像时出现认证错误:
DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Head \"https://<my-registry>.azurecr.io/v2/<image>/manifests/latest\": unauthorized: authentication required, visit https://aka.ms/acr/authorization for more information."}
我的配置
- App Service托管身份:已启用(状态为On),在ACR资源范围分配了ACR Pull角色
- ACR托管身份:已启用(状态为On)
- 部署流水线(Azure DevOps):构建并推送Docker镜像至ACR,配置片段如下:
trigger: - main variables: buildConfiguration: 'Release' appServiceName: 'myAppService' backendImageName: 'myregistry.azurecr.io/my-backend' frontendImageName: 'myregistry.azurecr.io/my-frontend' resourceGroup: 'myResourceGroup' subscriptionId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' stages: # Stage 1: Build and Push Docker Images - stage: BuildAndPush displayName: Build and Push Docker Images to Azure Container Registry jobs: - job: BuildAndPush displayName: Build and Push Backend and Frontend Docker Images pool: vmImage: 'ubuntu-latest' # Use Ubuntu for Docker tasks steps: # Step 1: Login to Azure Container Registry - task: Docker@2 displayName: Login to Azure Container Registry inputs: command: login containerRegistry: 'my_container_registry' # Step 2: Build and Push Backend Docker Image - task: Docker@2 displayName: Build and Push Backend Docker Image inputs: command: buildAndPush dockerfile: ./Dockerfile context: ./Backend.Api repository: my-backend containerRegistry: 'my_container_registry' tags: | latest $(Build.BuildId) # Step 3: Build and Push Frontend Docker Image - task: Docker@2 displayName: Build and Push Frontend Docker Image inputs: command: buildAndPush dockerfile: ./Frontend.Client/Dockerfile context: ./Frontend.Client repository: my-frontend containerRegistry: 'my_container_registry' tags: | latest $(Build.BuildId) # Stage 2: Deploy to Azure - stage: Deploy displayName: Deploy Docker Containers to Azure App Service dependsOn: BuildAndPush condition: succeeded() jobs: - job: DeployToAzure displayName: Deploy Containers to Azure App Service pool: vmImage: 'ubuntu-latest' steps: # Step 1: Login to Azure CLI - task: AzureCLI@2 displayName: Login to Azure inputs: azureSubscription: 'Azure subscription 1(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)' scriptType: bash scriptLocation: inlineScript inlineScript: | echo "Logging in to Azure CLI" - task: Docker@2 displayName: Login to Azure Container Registry inputs: command: login containerRegistry: 'my_container_registry' # Step 2: Generate Docker Compose File - script: | echo " version: '3.8' services: backend: image: $(backendImageName):latest ports: - 5000:80 frontend: image: $(frontendImageName):latest ports: - 3000:80 " > docker-compose.yml displayName: Generate Docker Compose File # Step 3: Configure App Service for Multi-Container Deployment - task: AzureCLI@2 displayName: Configure Azure App Service with Docker Compose inputs: azureSubscription: 'Azure subscription 1(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)' scriptType: bash scriptLocation: inlineScript inlineScript: | az webapp config container set \ --name $(appServiceName) \ --resource-group $(resourceGroup) \ --subscription $(subscriptionId) \ --multicontainer-config-type compose \ --multicontainer-config-file docker-compose.yml # Step 4: Restart App Service to Apply Changes - task: AzureCLI@2 displayName: Restart Azure App Service inputs: azureSubscription: 'Azure subscription 1(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)' scriptType: bash scriptLocation: inlineScript inlineScript: | az webapp restart \ --name $(appServiceName) \ --resource-group $(resourceGroup) \ --subscription $(subscriptionId)
- 最终用于App Service的docker-compose.yml:
version: '3.8' services: backend: image: <my-registry>.azurecr.io/backend:latest ports: - 5000:80 frontend: image: <my-registry>.azurecr.io/frontend:latest ports: - 3000:80
已执行的排查步骤
- 确认App Service和ACR均已启用托管身份
- 确认App Service的托管身份已分配ACR Pull角色
- 确认Docker镜像存在于ACR中,本地可通过同一docker-compose.yml拉取
- 检查是否存在网络限制或防火墙阻断App Service与ACR的连接
错误日志
DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Head \"https://<my-registry>.azurecr.io/v2/<image>/manifests/latest\": unauthorized: authentication required, visit https://aka.ms/acr/authorization for more information."}
问题
- 需额外配置哪些项才能让App Service通过托管身份从ACR拉取镜像?
- 是否有特定的网络安全组(NSG)设置需要验证?
预期结果
- App Service使用系统分配的托管身份向ACR认证
- ACR Pull角色具备足够的镜像拉取权限
- 容器可成功启动,无认证或授权问题
解决方案
1. 配置App Service使用托管身份认证ACR
执行以下Azure CLI命令,明确指定App Service使用托管身份连接ACR:
az webapp config container set \ --name <你的App Service名称> \ --resource-group <你的资源组名称> \ --docker-registry-server-url https://<你的ACR名称>.azurecr.io \ --enable-managed-identity true
这条命令会让App Service自动使用系统托管身份完成ACR认证,无需在docker-compose中配置凭证。
2. 验证ACR Pull角色分配的准确性
- 确认角色是直接分配在ACR资源上,而非父资源组或订阅(虽然层级分配也生效,但直接绑定ACR更精准)。
- 核对角色分配的主体:在App Service的“标识”页面复制系统托管身份的Object ID,然后在ACR的“访问控制(IAM)”中确认该Object ID已被授予ACR Pull角色。
3. 检查ACR的网络访问配置
- 若ACR启用了防火墙:将App Service的所有出站IP地址添加到ACR的允许列表(可在App Service“属性”页面获取出站IP);或开启ACR的“允许受信任的Microsoft服务访问”选项。
- 若ACR使用专用端点:确保App Service所在虚拟网络能访问该专用端点,且配置了正确的私有DNS区域(用于解析ACR域名到专用IP)。
4. 确认多容器部署配置无冲突
- docker-compose文件中不要添加任何认证相关的配置(如
credentials字段),避免覆盖托管身份认证逻辑。 - 检查镜像名称是否完全正确,包括注册表域名、仓库名、标签,确保与ACR中的镜像一致。
5. NSG设置验证
- 检查App Service所在子网的NSG出站规则:允许HTTPS(443端口)流量访问ACR的IP范围或域名。
- 检查ACR所在子网的NSG入站规则:允许来自App Service子网的HTTPS流量。
内容的提问来源于stack exchange,提问作者GRS
相关产品推荐
相关产品推荐

