使用Python从ACR创建Azure容器实例遇InaccessibleImage错误求助
解决ACI拉取ACR镜像时的InaccessibleImage错误
以下是针对你代码问题的具体修正和调试建议:
代码中的核心问题及修正
1. 未配置ACR实例名称
代码中acr_name = ""为空字符串,必须替换为你的实际ACR实例名称。
2. 错误获取ACR凭证
原代码中直接从acr对象获取用户名和密码的方式完全错误,正确的做法是调用list_credentials方法:
# 获取ACR凭证 acr_credentials = acr_client.registries.list_credentials(resource_group_name, acr_name) registry_username = acr_credentials.username registry_password = acr_credentials.passwords[0].value # 取第一个密码
另外,确保你的ACR已经启用了管理员用户(如果使用管理员凭证拉取),或者服务主体拥有AcrPull权限。
3. 未向ACI提供镜像拉取凭证
创建容器组时必须添加image_registry_credentials字段,否则ACI无法认证到ACR:
"image_registry_credentials": [ { "server": registry_login_server, "username": registry_username, "password": registry_password } ]
4. 硬编码资源参数,未使用传入值
原代码中CPU和内存写死为2和6,需要替换为传入的参数:
"cpu": float(cpu_request), "memoryInGB": float(memory_request.replace("Gi", "")) # 处理1Gi这样的格式
5. 容器命令格式问题
如果传入的是复杂Shell命令,直接用[command]可能无法正确执行,需要改为:
"command": ["/bin/sh", "-c", command]
修正后的完整代码
import argparse from azure.identity import ClientSecretCredential from azure.mgmt.containerinstance import ContainerInstanceManagementClient from azure.mgmt.containerregistry import ContainerRegistryManagementClient import os parser = argparse.ArgumentParser(description="Create a container in Azure using client credentials.") parser.add_argument("--client-id", required=True, help="Azure Active Directory client ID") parser.add_argument("--client-secret", required=True, help="Azure Active Directory client secret") parser.add_argument("--tenant-id", required=True, help="Azure Active Directory tenant ID") parser.add_argument("--container-name", required=True, help="Name for the container") parser.add_argument("--container-resource-group", required=True, help="Resource group name") parser.add_argument("--command", required=True, help="Command to run inside the container") parser.add_argument("--image", required=True, help="Container image to use (format: repo:tag)") parser.add_argument("--subscription-id", required=False, help="Azure subscription ID (optional, uses environment variable by default)") parser.add_argument("--cpu-request", required=True, help="CPU request for the container (e.g., 0.5 for half a core)") parser.add_argument("--memory-request", required=True, help="Memory request for the container (e.g., 1Gi)") parser.add_argument("--acr-name", required=True, help="Name of your Azure Container Registry instance") args = parser.parse_args() def create_container(client_id, client_secret, tenant_id, container_name, resource_group_name, command, image, acr_name, subscription_id=None, cpu_request=None, memory_request=None): if not subscription_id: subscription_id = os.environ.get("AZURE_SUBSCRIPTION_ID") if not subscription_id: raise ValueError("Subscription ID is required, either provide it as an argument or set the AZURE_SUBSCRIPTION_ID environment variable.") # 初始化凭证 credential = ClientSecretCredential( client_id=client_id, client_secret=client_secret, tenant_id=tenant_id ) # 获取ACR信息和凭证 acr_client = ContainerRegistryManagementClient(credential, subscription_id=subscription_id) acr = acr_client.registries.get(resource_group_name, acr_name) acr_credentials = acr_client.registries.list_credentials(resource_group_name, acr_name) registry_login_server = acr.login_server registry_username = acr_credentials.username registry_password = acr_credentials.passwords[0].value # 处理内存参数,去除Gi后缀 memory_value = float(memory_request.replace("Gi", "")) # 创建容器实例 client = ContainerInstanceManagementClient(credential, subscription_id=subscription_id) container_group = client.container_groups.begin_create_or_update( resource_group_name, container_name, { "location": "eastus", "os_type": "Linux", "image_registry_credentials": [ { "server": registry_login_server, "username": registry_username, "password": registry_password } ], "containers": [ { "name": container_name, "properties": { "image": f"{registry_login_server}/{image}", "command": ["/bin/sh", "-c", command], "resources": { "requests": { "cpu": float(cpu_request), "memoryInGB": memory_value } } } } ] } ).result() print(f"Container '{container_name}' created with ID: {container_group.id}") if __name__ == "__main__": create_container( args.client_id, args.client_secret, args.tenant_id, args.container_name, args.container_resource_group, args.command, args.image, args.acr_name, args.subscription_id, args.cpu_request, args.memory_request )
额外调试建议
- 验证镜像存在:使用Azure CLI确认ACR中的镜像存在:
az acr repository show --name <your-acr-name> --image <your-image>:<your-tag> - 检查服务主体权限:确保你的Client ID拥有ACR的
AcrPull角色权限,可以通过Azure CLI配置:az role assignment create --assignee <client-id> --role AcrPull --scope /subscriptions/<subscription-id>/resourceGroups/<rg-name>/providers/Microsoft.ContainerRegistry/registries/<acr-name> - 查看ACI事件日志:如果创建失败,通过Azure CLI查看容器组的事件日志,获取更详细的错误信息:
az container show --resource-group <rg-name> --name <container-group-name> --query instanceView.events - 测试凭证有效性:用获取到的ACR凭证手动登录测试:
docker login <acr-login-server> -u <username> -p <password>
内容的# 问题分析与修复方案
出现InaccessibleImage错误的核心原因是ACI无法通过正确凭据访问ACR镜像,同时代码存在多处逻辑错误,以下是具体修复步骤:
1. 修复ACR凭据获取逻辑
原代码错误地将布尔值admin_user_enabled作为用户名,且无法通过acr.admin_user_password获取密码(ACR的get接口不返回明文密码),需改用list_credentials方法获取有效凭据:
# 替换原ACR凭据获取代码 acr_name = "你的ACR名称" # 填写实际ACR名称 # 获取ACR凭据 acr_credentials = acr_client.registries.list_credentials(resource_group_name, acr_name) registry_login_server = acr.login_server # 取ACR默认的管理员凭据 registry_username = acr_credentials.username registry_password = acr_credentials.passwords[0].value
2. 为ACI添加ACR认证凭据
创建容器组时必须配置image_registry_credentials字段,让ACI能认证到ACR:
container_group = client.container_groups.begin_create_or_update( resource_group_name, container_name, { "location": "eastus", "os_type": "Linux", # 添加ACR认证信息 "image_registry_credentials": [ { "server": registry_login_server, "username": registry_username, "password": registry_password } ], "containers": [ { "name": container_name, "properties": { "image": f"{registry_login_server}/{image}", # 修复命令格式:复杂shell命令需通过sh解析 "command": ["/bin/sh", "-c", command], "resources": { "requests": { # 替换硬编码,使用传入参数并转换类型 "cpu": float(cpu_request), # 修复拼写错误:原代码为MemoryinGB,正确为MemoryInGB "memoryInGB": float(memory_request.replace("Gi", "")) } } } } ] } ).result()
3. 前置检查项
- 确保ACR的管理员用户已启用:在Azure门户的ACR设置中开启"管理员用户"
- 确认镜像存在:检查ACR中
{registry_login_server}/{image}对应的镜像和标签是否有效 - 权限验证:若使用服务主体而非管理员用户,需为该主体分配ACR的
AcrPull角色
修改后的完整代码
import argparse from azure.identity import ClientSecretCredential from azure.mgmt.containerinstance import ContainerInstanceManagementClient from azure.mgmt.containerregistry import ContainerRegistryManagementClient import os parser = argparse.ArgumentParser(description="Create a container in Azure using client credentials.") parser.add_argument("--client-id", required=True, help="Azure Active Directory client ID") parser.add_argument("--client-secret", required=True, help="Azure Active Directory client secret") parser.add_argument("--tenant-id", required=True, help="Azure Active Directory tenant ID") parser.add_argument("--container-name", required=True, help="Name for the container") parser.add_argument("--container-resource-group", required=True, help="Resource group name") parser.add_argument("--command", required=True, help="Command to run inside the container") parser.add_argument("--image", required=True, help="Container image to use (format: repo/image:tag)") parser.add_argument("--subscription-id", required=False, help="Azure subscription ID (optional, uses environment variable by default)") parser.add_argument("--cpu-request", required=True, help="CPU request for the container (e.g., 0.5)") parser.add_argument("--memory-request", required=True, help="Memory request for the container (e.g., 1)") parser.add_argument("--acr-name", required=True, help="Name of your Azure Container Registry") args = parser.parse_args() def create_container(client_id, client_secret, tenant_id, container_name, resource_group_name, command, image, acr_name, subscription_id=None, cpu_request=None, memory_request=None): if not subscription_id: subscription_id = os.environ.get("AZURE_SUBSCRIPTION_ID") if not subscription_id: raise ValueError("Subscription ID is required, either provide it as an argument or set the AZURE_SUBSCRIPTION_ID environment variable.") credential = ClientSecretCredential( client_id=client_id, client_secret=client_secret, tenant_id=tenant_id ) # 获取ACR信息和凭据 acr_client = ContainerRegistryManagementClient(credential, subscription_id=subscription_id) acr = acr_client.registries.get(resource_group_name, acr_name) acr_credentials = acr_client.registries.list_credentials(resource_group_name, acr_name) registry_login_server = acr.login_server registry_username = acr_credentials.username registry_password = acr_credentials.passwords[0].value # 创建ACI client = ContainerInstanceManagementClient(credential, subscription_id=subscription_id) container_group = client.container_groups.begin_create_or_update( resource_group_name, container_name, { "location": "eastus", "os_type": "Linux", "image_registry_credentials": [ { "server": registry_login_server, "username": registry_username, "password": registry_password } ], "containers": [ { "name": container_name, "properties": { "image": f"{registry_login_server}/{image}", "command": ["/bin/sh", "-c", command], "resources": { "requests": { "cpu": float(cpu_request), "memoryInGB": float(memory_request) } } } } ] } ).result() print(f"Container '{container_name}' created with ID: {container_group.id}") if __name__ == "__main__": create_container( args.client_id, args.client_secret, args.tenant_id, args.container_name, args.container_resource_group, args.command, args.image, args.acr_name, args.subscription_id, args.cpu_request, args.memory_request )
调试建议
- 手动验证ACR凭据:用
docker login {registry_login_server}输入用户名密码,确认能正常拉取镜像 - 检查网络配置:若ACR配置了私有网络,需确保ACI部署在同一虚拟网络或ACR允许ACI访问
- 查看ACI日志:创建失败后,在Azure门户查看容器日志获取更详细的错误信息
内容的提问来源于stack exchange,提问作者Aman Chagti
相关产品推荐
相关产品推荐

