你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Azure 容器注册表适用于 Java 的客户端库 - 版本 1.2.2

Azure 容器注册表允许在专用注册表中存储和管理所有类型的容器部署的容器映像和项目。

使用 Azure 容器注册表客户端库执行以下操作:

  • 列出注册表中的映像或项目
  • 获取图像和项目、存储库和标记的元数据
  • 设置注册表项的读取/写入/删除属性
  • 删除映像和项目、存储库和标记

源代码 | 包 (Maven) | 产品文档 | 样品

入门

先决条件

添加包

包括 BOM 文件

请将 azure-sdk-bom 包含在项目中,以依赖于库的正式发布 (GA) 版本。 在以下代码段中,将 {bom_version_to_target} 占位符替换为版本号。 若要详细了解 BOM,请参阅 AZURE SDK BOM 自述文件

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-sdk-bom</artifactId>
            <version>{bom_version_to_target}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

然后在 dependencies 节中包含直接依赖项,不带版本标记,如下所示。

<dependencies>
  <dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-containers-containerregistry</artifactId>
  </dependency>
</dependencies>

包括直接依赖项

<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-containers-containerregistry</artifactId>
  <version>1.2.2</version>
</dependency>

对客户端进行身份验证

Azure 标识库为身份验证提供简单的 Azure Active Directory 支持。 请注意,下面的所有示例都假定你有一个终结点,该终结点是包含登录服务器名称和前缀的 https:// URL。 有关详细信息,请参阅 Azure 容器注册表 门户

DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
ContainerRegistryClient registryClient = new ContainerRegistryClientBuilder()
    .endpoint(endpoint)
    .credential(credential)
    .buildClient();
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
ContainerRegistryAsyncClient registryClient = new ContainerRegistryClientBuilder()
    .endpoint(endpoint)
    .credential(credential)
    .buildAsyncClient();

有关将 AAD 与 Azure 容器注册表 配合使用的详细信息,请参阅服务的身份验证概述

使用 ARM AAD 令牌进行身份验证

默认情况下,适用于 Java 的容器注册表 SDK 使用 ACR 访问令牌。 如果要使用 ARM AAD 令牌进行身份验证并启用相应的策略,请确保在生成容器注册表客户端时设置受众。 有关如何检查 ARM 身份验证策略配置的信息,请参阅 ACR CLI 参考

ContainerRegistryAudience 值特定于云:

ContainerRegistryClient registryClient = new ContainerRegistryClientBuilder()
    .endpoint(getEndpoint())
    .credential(credential)
    .audience(ContainerRegistryAudience.AZURE_RESOURCE_MANAGER_PUBLIC_CLOUD)
    .buildClient();

registryClient
    .listRepositoryNames()
    .forEach(name -> System.out.println(name));

国家云

若要使用 国家云中的注册表进行身份验证,需要对客户端配置进行以下添加:

  • 按照authorityHost标识客户端库文档在凭据生成器中设置
  • 如果为容器注册表资源禁用了 ACR 访问令牌身份验证,则需要在容器注册表客户端生成器上配置受众。
ContainerRegistryClient registryClient = new ContainerRegistryClientBuilder()
    .endpoint(getEndpoint())
    .credential(credential)
    // only if ACR access tokens are disabled or not supported
    .audience(ContainerRegistryAudience.AZURE_RESOURCE_MANAGER_CHINA)
    .buildClient();

registryClient
    .listRepositoryNames()
    .forEach(name -> System.out.println(name));

匿名访问支持

如果在没有任何凭据的情况下实例化生成器,SDK 会为匿名拉取模式创建服务客户端。 用户必须在已启用匿名拉取的注册表上使用此设置。 在此模式下,用户只能调用 listRepositoryNames 方法及其重载。 所有其他调用都将失败。 有关详细信息,请阅读 匿名拉取访问

ContainerRegistryClient registryClient = new ContainerRegistryClientBuilder()
    .endpoint(endpoint)
    .buildClient();
ContainerRegistryAsyncClient registryClient = new ContainerRegistryClientBuilder()
    .endpoint(endpoint)
    .buildAsyncClient();

关键概念

注册表存储 Docker 映像和 OCI 项目。 映像或项目由清单和各层组成 。 映像清单描述构成映像的层,并由其 摘要唯一标识。 还可以对图像进行“标记”,以为其提供可读别名。 图像或项目可以有零个或多个与之关联的 标记 ,并且每个标记唯一标识图像。 共享同名但标记不同的映像集合称为 存储库

有关详细信息,请参阅 容器注册表概念

示例

同步示例

注册表操作

本部分包含 ContainerRegistryClient 示例。

列出存储库名称

循环访问注册表中的存储库集合。

registryClient.listRepositoryNames().forEach(repository -> System.out.println(repository));

列出具有匿名访问的项目标记

RegistryArtifact image = anonymousClient.getArtifact(repositoryName, digest);

PagedIterable<ArtifactTagProperties> tags = image.listTagProperties();

System.out.printf(String.format("%s has the following aliases:", image.getFullyQualifiedReference()));

for (ArtifactTagProperties tag : tags) {
    System.out.printf(String.format("%s/%s:%s", anonymousClient.getEndpoint(), repositoryName, tag.getName()));
}

编辑项目属性

RegistryArtifact image = registryClient.getArtifact(repositoryName, digest);

image.updateTagProperties(
    tag,
    new ArtifactTagProperties()
        .setWriteEnabled(false)
        .setDeleteEnabled(false));

删除映像

final int imagesCountToKeep = 3;
for (String repositoryName : registryClient.listRepositoryNames()) {
    final ContainerRepository repository = registryClient.getRepository(repositoryName);

    // Obtain the images ordered from newest to oldest
    PagedIterable<ArtifactManifestProperties> imageManifests =
        repository.listManifestProperties(
            ArtifactManifestOrder.LAST_UPDATED_ON_DESCENDING,
            Context.NONE);

    imageManifests.stream().skip(imagesCountToKeep)
        .forEach(imageManifest -> {
            System.out.printf(String.format("Deleting image with digest %s.%n", imageManifest.getDigest()));
            System.out.printf("    This image has the following tags: ");

            for (String tagName : imageManifest.getTags()) {
                System.out.printf("        %s:%s", imageManifest.getRepositoryName(), tagName);
            }

            repository.getArtifact(imageManifest.getDigest()).delete();
        });
}

删除引发匿名访问的存储库

final String endpoint = getEndpoint();
final String repositoryName = getRepositoryName();

ContainerRegistryClient anonymousClient = new ContainerRegistryClientBuilder()
    .endpoint(endpoint)
    .buildClient();

try {
    anonymousClient.deleteRepository(repositoryName);
    System.out.println("Unexpected Success: Delete is not allowed on anonymous access");
} catch (ClientAuthenticationException ex) {
    System.out.println("Expected exception: Delete is not allowed on anonymous access");
}

Blob 和清单操作

本节包含的示例 ContainerRegistryContentClient 演示如何上传和下载图像。

首先,我们需要创建 Blob 客户端。

DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
ContainerRegistryContentClient contentClient = new ContainerRegistryContentClientBuilder()
    .endpoint(endpoint)
    .credential(credential)
    .repositoryName(repository)
    .buildClient();

上传图像

若要上传完整映像,需要上传各个层和配置。 之后,我们可以上传描述图像或项目的清单,并为其分配标记。

BinaryData configContent = BinaryData.fromObject(Collections.singletonMap("hello", "world"));

UploadRegistryBlobResult configUploadResult = contentClient.uploadBlob(configContent);
System.out.printf("Uploaded config: digest - %s, size - %s\n", configUploadResult.getDigest(), configContent.getLength());

OciDescriptor configDescriptor = new OciDescriptor()
    .setMediaType("application/vnd.unknown.config.v1+json")
    .setDigest(configUploadResult.getDigest())
    .setSizeInBytes(configContent.getLength());

BinaryData layerContent = BinaryData.fromString("Hello Azure Container Registry");
UploadRegistryBlobResult layerUploadResult = contentClient.uploadBlob(layerContent);
System.out.printf("Uploaded layer: digest - %s, size - %s\n", layerUploadResult.getDigest(), layerContent.getLength());

OciImageManifest manifest = new OciImageManifest()
    .setConfiguration(configDescriptor)
    .setSchemaVersion(2)
    .setLayers(Collections.singletonList(
        new OciDescriptor()
            .setDigest(layerUploadResult.getDigest())
            .setSizeInBytes(layerContent.getLength())
            .setMediaType("application/octet-stream")));

SetManifestResult manifestResult = contentClient.setManifest(manifest, "latest");
System.out.printf("Uploaded manifest: digest - %s\n", manifestResult.getDigest());

下载映像

若要下载完整映像,需要下载其清单,然后下载各个层和配置。

GetManifestResult manifestResult = contentClient.getManifest("latest");

OciImageManifest manifest = manifestResult.getManifest().toObject(OciImageManifest.class);
System.out.printf("Got manifest:\n%s\n", PRETTY_PRINT.writeValueAsString(manifest));

String configFileName = manifest.getConfiguration().getDigest() + ".json";
contentClient.downloadStream(manifest.getConfiguration().getDigest(), createFileChannel(configFileName));
System.out.printf("Got config: %s\n", configFileName);

for (OciDescriptor layer : manifest.getLayers()) {
    contentClient.downloadStream(layer.getDigest(), createFileChannel(layer.getDigest()));
    System.out.printf("Got layer: %s\n", layer.getDigest());
}

删除 Blob

GetManifestResult manifestResult = contentClient.getManifest("latest");

OciImageManifest manifest = manifestResult.getManifest().toObject(OciImageManifest.class);
for (OciDescriptor layer : manifest.getLayers()) {
    contentClient.deleteBlob(layer.getDigest());
}

删除清单

GetManifestResult manifestResult = contentClient.getManifest("latest");
contentClient.deleteManifest(manifestResult.getDigest());

疑难解答

有关如何诊断各种故障方案的详细信息,请参阅 故障排除指南

后续步骤

贡献

本项目欢迎贡献和建议。 大多数贡献要求你同意贡献者许可协议 (CLA),并声明你有权(并且确实有权)授予我们使用你的贡献的权利。 有关详细信息,请访问 cla.microsoft.com

此项目采用了 Microsoft 开放源代码行为准则。 有关详细信息,请参阅行为准则常见问题解答,或如果有任何其他问题或意见,请与 联系。

曝光数