You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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
    )

调试建议

  1. 手动验证ACR凭据:用docker login {registry_login_server}输入用户名密码,确认能正常拉取镜像
  2. 检查网络配置:若ACR配置了私有网络,需确保ACI部署在同一虚拟网络或ACR允许ACI访问
  3. 查看ACI日志:创建失败后,在Azure门户查看容器日志获取更详细的错误信息

内容的提问来源于stack exchange,提问作者Aman Chagti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 19:34:54