常见问题解答 - Azure Stack Hub 上的 Azure 容器注册表

本文解答有关 Azure 容器注册表的常见问题和已知问题。

有关注册表故障排除指南,请参阅:

资源管理

是否可以使用资源管理器模板在 Azure Stack Hub 上创建 Azure 容器注册表?

是的。 下面是 可用于创建注册表的模板。 此模板适用于 Azure 公有云。 若要针对 Azure Stack Hub 使用此模板,请将 API 版本修改为 2019-05-01,否则无法部署。

是否会在 Azure Stack Hub 上对 ACR 中的映像执行安全漏洞扫描?

否。 目前,部署在 Azure Stack Hub 上的注册表未与 Azure 安全中心进行集成。 可以利用第三方和开源选项来满足连接或断开 Azure Stack Hub 部署连接的需求。

如何使用 Azure 容器注册表配置 Kubernetes?

请参阅 Kubernetes 的文档以及适用于 Azure Kubernetes 服务的步骤。

如何获取容器注册表的管理员凭据?

重要

管理员用户帐户专门用于单个用户访问注册表,主要用于测试目的。 建议不要与多个用户共享管理员帐户凭据。 建议用户和服务主体在无外设方案中使用单个标识。 请参阅身份验证概述

在获取管理员凭据之前,请确保已启用注册表的管理员用户。

使用 Azure CLI 获取凭据:

az acr credential show -n myRegistry

使用 Azure PowerShell:

Invoke-AzureRmResourceAction -Action listCredentials -ResourceType Microsoft.ContainerRegistry/registries -ResourceGroupName myResourceGroup -ResourceName myRegistry

如何在资源管理器模板中获取管理员凭据?

重要

管理员用户帐户专门用于单个用户访问注册表,主要用于测试目的。 建议不要与多个用户共享管理员帐户凭据。 建议用户和服务主体在无外设方案中使用单个标识。 请参阅身份验证概述

在获取管理员凭据之前,请确保已启用注册表的管理员用户。

获取第一个密码:

{
    "password": "[listCredentials(resourceId('Microsoft.ContainerRegistry/registries', 'myRegistry'), '2017-10-01').passwords[0].value]"
}

获取第二个密码:

{
    "password": "[listCredentials(resourceId('Microsoft.ContainerRegistry/registries', 'myRegistry'), '2017-10-01').passwords[1].value]"
}

如何将 Azure 容器注册表中的容器映像推送到运行 Kubernetes 的、已断开连接的 Azure Stack Hub 部署?

可以通过本地网络从已有所需容器映像的计算机执行计算机到计算机映像传输。 为此,请按以下步骤操作:

  1. 首先,使用 docker CLI 和 docker pull 命令,通过具有 Internet 连接的计算机检索所需的容器映像。 有关详细信息,请参阅将容器映像导入容器注册表

  2. 导入所需的映像后,将计算机运送到断开连接的 Azure 中心实例的位置。

  3. 使用 docker tagdocker push 命令标记映像并将其推送到 Azure Stack Hub 存储库上的本地 Azure 容器注册表。

注册表操作

如何访问 Docker 注册表 HTTP API V2?

ACR 支持 Docker 注册表 HTTP API V2。 可通过 https://<your registry login server>/v2/ 访问 API。 示例: https://mycontainerregistry.azsacr.<regionname>.<fqdn>/v2/

如何删除不由存储库中的任何标记引用的所有清单?

如果你使用的是 bash:

az acr manifest list-metadata --name myRepository --registry myRegistry --query "[?tags[0]==null].digest" --output tsv  | xargs -I% az acr repository delete --name myRegistry --image myRepository@%

对于 PowerShell:

az acr manifest list-metadata --name myRepository --registry myRegistry --query "[?tags[0]==null].digest" --output tsv | %{ az acr repository delete --name myRegistry --image myRepository@$_ }

注意

在 delete 命令中添加 --yes 可跳过确认。

有关详细信息,请参阅删除 Azure 容器注册表中的容器映像

为何删除映像后,注册表配额用量未减少?

如果其他容器映像仍在引用基础层,则可能会发生这种情况。 如果删除不带引用的映像,则注册表用量在几分钟后即会更新。

如何验证存储配额更改?

使用以下 Docker 文件创建使用 1GB 层的映像。 这可以确保该映像的某个层不会由注册表中的任何其他映像共享。

FROM alpine
RUN dd if=/dev/urandom of=1GB.bin  bs=32M  count=32
RUN ls -lh 1GB.bin

使用 Docker CLI 生成映像并将其推送到注册表。

docker build -t myregistry.azsacr.<regionname>.<fqdn>/1gb:latest .
docker push myregistry.azsacr.<regionname>.<fqdn>/1gb:latest

在 Azure Stack Hub 门户中应该可以看到存储用量已增加,也可以使用 CLI 查询用量。

az acr show-usage -n myregistry

使用 Azure CLI 或门户删除映像,并在几分钟后检查更新的用量。

az acr repository delete -n myregistry --image 1gb

在容器中运行 CLI 时如何对注册表进行身份验证?

需要通过装载 Docker 套接字来运行 Azure CLI 容器:

docker run -it -v /var/run/docker.sock:/var/run/docker.sock azuresdk/azure-cli-python:dev

在容器中安装 docker

apk --update add docker

然后对注册表进行身份验证:

az acr login -n MyRegistry

如何启用 TLS 1.2?

使用任何最近发布的 Docker 客户端(18.03.0 和更高版本)启用 TLS 1.2。

重要

从 2020 年 1 月 13 日开始,Azure 容器注册表将要求服务器和应用程序的所有安全连接都使用 TLS 1.2。 对 TLS 1.0 和 1.1 的支持将停用。

Azure Stack Hub 上的 Azure 容器注册表是否支持内容信任?

不支持,当前 Azure Stack Hub 上的 Azure 容器注册表版本仅支持“标准”SKU,并不支持内容信任。

在无权管理注册表资源的情况下如何授予提取或推送映像的访问权限?

ACR 支持提供不同权限级别的自定义角色。 具体而言,AcrPullAcrPush 角色允许用户在无权管理 Azure 中的注册表资源的情况下提取和/或推送映像。

  • Azure Stack Hub 门户:“注册表”>“访问控制(IAM)”>“添加”(为“角色”选择 AcrPullAcrPush)。

  • Azure CLI:运行以下命令找到注册表的资源 ID:

    az acr show -n myRegistry
    

    然后,可将 AcrPullAcrPush 角色分配给用户(以下示例使用 AcrPull):

    az role assignment create --scope resource_id --role AcrPull --assignee user@example.com
    

    或者,将角色分配到由应用程序 ID 标识的服务主体:

    az role assignment create --scope resource_id --role AcrPull --assignee 00000000-0000-0000-0000-000000000000
    

然后,被分配者可以验证和访问注册表中的映像。

  • 对注册表进行身份验证:

    az acr login -n myRegistry 
    
  • 列出存储库:

    az acr repository list -n myRegistry
    
  • 提取映像:

    docker pull myregistry.azsacr.<regionname>.<fqdn>/hello-world
    

如果只使用 AcrPullAcrPush 角色,则被分配者将无权管理 Azure 中的注册表资源。 例如,az acr listaz acr show -n myRegistry 不会显示注册表。

如何将不可分发层推送到注册表?

清单中的不可分发层包含一个 URL 参数,可以通过该参数提取内容。 启用不可分发层推送的一些可能用例适用于:网络受限制的注册表、具有受限访问权限的气隙注册表,或没有 Internet 连接的注册表。

例如,如果你设置了 NSG 规则,使 VM 只能从你的 Azure 容器注册表中拉取映像,则 Docker 会让从外部/不可分发层进行的拉取失败。 例如,Windows Server Core 映像在其清单中会包含对 Azure 容器注册表的外部层引用,所以在此情况下将无法拉取。

若要启用不可分发层的推送,请执行以下操作:

  1. 编辑 daemon.json 文件,该文件在 Linux 主机上位于 /etc/docker/ 中,在 Windows Server 上位于 C:\ProgramData\docker\config\daemon.json 中。 假设文件之前为空,请添加以下内容:

    {
      "allow-nondistributable-artifacts": ["myregistry.azsacr.<regionname>.<fqdn>"]
    }
    

    注意

    值是注册表地址的数组,各个地址之间以逗号分隔。

  2. 保存并退出该文件。

  3. 重启 Docker。

将映像推送到列表中的注册表时,它们的不可分发层会被推送到注册表。

警告

不可分发项目通常在其分发和共享方式与位置方面存在限制。 请仅在将项目推送到专用注册表时使用此功能。 请确保遵守与重新分发不可分发项目相关的任何条款。

诊断和运行状况检查

使用“az acr check-health”检查运行状况

若要排查常见的环境和注册表问题,请参阅检查 Azure 容器注册表的运行状况

Docker pull 失败,出现错误:net/http: 等待连接时取消了请求(等待标头时超过了 Client.Timeout)

  • 如果此错误是暂时性的,则重试后,提取将会成功。
  • 如果 docker pull 连续失败,则原因可能是 Docker 守护程序出现了问题。 重启 Docker 守护程序通常可以缓解此问题。
  • 如果重启 Docker 守护程序后仍旧出现此问题,则原因可能是计算机上出现了一些网络连接问题。 若要检查计算机上的常规网络是否正常,请运行以下命令来测试终结点连接。 包含此连接性检查命令的最低 az acr 版本为 2.2.9。 如果使用早期的版本,请升级 Azure CLI。
az acr check-health -n myRegistry
  • 始终应该对所有 Docker 客户端操作使用重试机制。

Docker 提取速度缓慢

使用工具测试计算机的网络下载速度。

Docker 推送速度缓慢

使用工具测试计算机的网络上传速度。

Docker 推送成功,但 Docker 提取失败并出现错误:未授权: 需要身份验证

默认启用 --signature-verification 的 Red Hat 版 Docker 守护程序可能会发生此错误。 可以运行以下命令来检查 Red Hat Enterprise Linux (RHEL) 或 Fedora 的 Docker 守护程序选项:

grep OPTIONS /etc/sysconfig/docker

例如,Fedora 28 服务器使用以下 Docker 守护程序选项:

OPTIONS='--selinux-enabled --log-driver=journald --live-restore'

如果缺少 --signature-verification=falsedocker pull 将会失败并出现如下所示的错误:

Trying to pull repository myregistry.azsacr.<regionname>.<fqdn>/myimage ...
unauthorized: authentication required

若要解决该错误:

  1. 将选项 --signature-verification=false 添加到 Docker 守护程序配置文件 /etc/sysconfig/docker。 例如:

    OPTIONS='--selinux-enabled --log-driver=journald --live-restore --signature-verification=false'

  2. 运行以下命令重启 Docker 守护程序服务:

    sudo systemctl restart docker.service
    

运行 man dockerd 可以找到 --signature-verification 的详细信息。

az acr login 成功,但 Docker 失败并出现错误:未授权: 需要身份验证

请确保使用全小写的服务器 URL(例如 docker push myregistry.azsacr.<regionname>.<fqdn>/myimage:latest),即使注册表资源名称是大写的或大小写混合的(例如 myRegistry)。

启用和获取 Docker 守护程序的调试日志

使用 debug 选项启动 dockerd。 首先创建 Docker 守护程序配置文件 (/etc/docker/daemon.json)(如果不存在),并添加 debug 选项:

{    
    "debug": true    
}

然后重启守护程序。 例如,对于 Ubuntu 14.04:

sudo service docker restart

可以在 Docker 文档中找到详细信息。

  • 日志可能在不同的位置生成,具体取决于所用的系统。 例如,对于 Ubuntu 14.04,日志位置为 /var/log/upstart/docker.log
    有关详细信息,请参阅 Docker 文档

  • 对于用于 Windows 的 Docker,将在 %LOCALAPPDATA%/docker/ 下生成日志。 但是,此位置不一定包含所有调试信息。

    若要访问完整的守护程序日志,可能需要执行一些额外的步骤:

    docker run --privileged -it --rm -v /var/run/docker.sock:/var/run/docker.sock -v /usr/local/bin/docker:/usr/local/bin/docker alpine sh
    
    docker run --net=host --ipc=host --uts=host --pid=host -it --security-opt=seccomp=unconfined --privileged --rm -v /:/host alpine /bin/sh
    chroot /host
    

    现在,可以访问运行 dockerd 的 VM 的所有文件。 日志位于 /var/log/docker.log

新用户权限在更新后可能不会立即生效

向服务主体授予新权限(新角色)时,更改可能不会立即生效。 有两种可能的原因:

  • Microsoft Entra角色分配延迟。 通常分配速度很快,但由于传播延迟,此过程可能需要几分钟时间。

  • ACR 令牌服务器上出现权限延迟。 分配权限最长可能需要 10 分钟。 若要缓解此情况,可以运行 docker logout,并在 1 分钟后使用同一用户的身份再次进行身份验证:

    docker logout myregistry.azsacr.<regionname>.<fqdn>
    docker login myregistry.azsacr.<regionname>.<fqdn>
    

未在 REST API 调用中以正确的格式指定身份验证信息

你可能会遇到 InvalidAuthenticationInfo 错误,尤其是结合选项 -L--location,跟踪重定向)使用 curl 工具时。 例如,结合 -L 选项和基本身份验证使用 curl 提取 Blob:

curl -L -H "Authorization: basic $credential" https://$registry.azurecr.io/v2/$repository/blobs/$digest

可能会生成以下响应:

<?xml version="1.0" encoding="utf-8"?>
<Error><Code>InvalidAuthenticationInfo</Code><Message>Authentication information is not given in the correct format. Check the value of Authorization header.
RequestId:00000000-0000-0000-0000-000000000000
Time:2019-01-01T00:00:00.0000000Z</Message></Error>

根本原因是某些 curl 实现使用原始请求中的标头跟踪重定向。

若要解决此问题,需要在不使用标头的情况下手动跟踪重定向。 使用 curl-D - 选项输出响应标头,然后提取 Location 标头:

redirect_url=$(curl -s -D - -H "Authorization: basic $credential" https://$registry.azurecr.io/v2/$repository/blobs/$digest | grep "^Location: " | cut -d " " -f2 | tr -d '\r')
curl $redirect_url

为何 Azure Stack Hub 门户未列出我的所有存储库或标记?

如果使用 Microsoft Edge/IE 浏览器,则最多可以查看 100 个存储库或标记。 如果注册表中的存储库或标记超过 100 个,则我们建议使用 Firefox 或 Chrome 浏览器将其列出。

为何 Azure Stack Hub 门户无法提取存储库或标记?

浏览器可能无法向服务器发送请求来提取存储库或标记。 可能有各种原因,例如:

  • 缺少网络连接
  • 防火墙
  • 从公共网络使用门户,而注册表仅允许专用访问
  • 广告阻止程序
  • DNS 错误

请与网络管理员联系,或者检查网络配置和连接性。 尝试使用 Azure CLI 来运行 az acr check-health -n yourRegistry,以便检查环境是否能够连接到容器注册表。 另外,也可尝试在浏览器中使用 incognito 或专用会话,避免使用任何过时的浏览器缓存或 Cookie。

为什么拉取或推送请求失败,并出现不受允许的操作?

以下是一些可能出现不允许进行操作的情况:

  • 映像或存储库可能已锁定,因此无法进行删除或更新。 可以使用 az acr show repository 命令来查看当前属性。
  • 如果映像处于隔离状态,则会禁用某些操作。 详细了解隔离
  • 注册表可能已达到其存储限制

存储库格式无效或不受支持

如果在存储库操作中指定存储库名称时出现“存储库格式不受支持”、“无效格式”或“请求的数据不存在”等错误,请检查名称的拼写和大小写。 有效的存储库名称只能包含小写字母数字字符、句点、短划线、下划线和正斜杠。

如何在 Windows 上收集 HTTP 跟踪?

先决条件

Windows 容器

将 Docker 代理配置为 127.0.0.1:8888

Linux 容器

查找 Docker VM 虚拟交换机的 IP:

(Get-NetIPAddress -InterfaceAlias "*Docker*" -AddressFamily IPv4).IPAddress

将 Docker 代理配置为上一命令的输出和端口 8888(例如 10.0.75.1:8888)

后续步骤