Compartilhar via


Registro de Contêiner do Azure biblioteca de clientes para .NET – versão 1.1.0

Registro de Contêiner do Azure permite armazenar e gerenciar imagens e artefatos de contêiner em um registro privado para todos os tipos de implantações de contêiner.

Use a biblioteca de clientes do Registro de Contêiner do Azure para:

  • Listar imagens ou artefatos em um registro
  • Obter metadados para imagens e artefatos, repositórios e marcas
  • Definir propriedades de leitura/gravação/exclusão em itens do registro
  • Excluir imagens e artefatos, repositórios e marcas

Código-fonte | Pacote (NuGet) | Documentação | de referência da API Documentação | da API RESTDocumentação do produto

Introdução

Para desenvolver o código do aplicativo .NET que possa se conectar a uma instância do Registro de Contêiner do Azure, você precisará da biblioteca Azure.Containers.ContainerRegistry.

Instalar o pacote

Instale a biblioteca de clientes do Registro de Contêiner do Azure para o .NET com o NuGet:

dotnet add package Azure.Containers.ContainerRegistry

Pré-requisitos

Você precisará de uma assinatura do Azure e de uma instância de serviço do Registro de Contêiner para que seu aplicativo se conecte.

Para criar um novo Registro de Contêiner, você pode usar o Portal do Azure, Azure PowerShell ou a CLI do Azure. Aqui está um exemplo de criação de um novo registro usando a CLI do Azure:

az acr create --name myregistry --resource-group myresourcegroup --location westus --sku Basic

Autenticar o cliente

Para que o aplicativo se conecte ao registro, você precisará criar um ContainerRegistryClient que possa se autenticar no registro. A biblioteca de Identidade do Azure facilita a adição do suporte do Azure Active Directory para autenticar clientes do SDK do Azure com seus serviços correspondentes do Azure.

Ao desenvolver e depurar seu aplicativo localmente, você poderá usar o seu usuário para se autenticar no registro. Uma forma de fazer isso é fazer a autenticação do seu usuário com a CLI do Azure e executar o aplicativo nesse ambiente. Se seu aplicativo estiver usando um cliente que tenha sido construído para autenticar-se com a DefaultAzureCredential, ele será autenticado corretamente no registro no ponto de extremidade especificado.

// Create a ContainerRegistryClient that will authenticate to your registry through Azure Active Directory
Uri endpoint = new Uri("https://myregistry.azurecr.io");
ContainerRegistryClient client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(),
    new ContainerRegistryClientOptions()
    {
        Audience = ContainerRegistryAudience.AzureResourceManagerPublicCloud
    });

Consulte o LEIAME de Identidade do Azure para obter mais abordagens para autenticação com DefaultAzureCredential, localmente e em ambientes de implantação. Para se conectar a registros em Nuvens do Azure não públicas, confira os exemplos abaixo.

Para obter mais informações sobre como usar o AAD com Registro de Contêiner do Azure, consulte a Visão geral de autenticação do serviço.

Principais conceitos

Um registro armazena imagens do Docker e artefatos OCI. Uma imagem ou um artefato consiste em um manifesto e em camadas. O manifesto de uma imagem descreve as camadas que compõem a imagem e é identificado exclusivamente por seu resumo. Uma imagem também pode ser "marcada" para dar a ela um alias legível por humanos. Uma imagem ou artefato pode ter zero ou mais marcas associadas a ela e cada marca identifica exclusivamente a imagem. Uma coleção de imagens que compartilham o mesmo nome, mas têm marcas diferentes, é conhecida como um repositório.

Para obter mais informações, consulte Conceitos do Registro de Contêiner.

Acesso thread-safe

Garantimos que todos os métodos de instância do cliente sejam thread-safe e independentes uns dos outros (diretriz). Isso garante que a recomendação para reutilizar instâncias de cliente seja sempre segura, mesmo entre threads.

Conceitos adicionais

Opções | do cliente Acessando a resposta | Operações de execução prolongada | Tratamento de falhas | Diagnostics | Zombando | Tempo de vida do cliente

Exemplos

Os snippets a seguir mostram breves exemplos de cenários comuns de desenvolvedor usando a biblioteca do SDK do ACR. Observe que cada exemplo pressupõe que há uma REGISTRY_ENDPOINT variável de ambiente definida como uma cadeia de caracteres que contém o https:// prefixo e o nome do servidor de logon, por exemplo"https://myregistry.azurecr.io".

Exemplos de sincronização

Exemplos assíncronos

Autenticação avançada

Operações de registro

Essa secion contém ContainerRegistryClient exemplos.

Listar repositórios

Itere na coleção de repositórios no registro.

// Get the service endpoint from the environment
Uri endpoint = new Uri(Environment.GetEnvironmentVariable("REGISTRY_ENDPOINT"));

// Create a new ContainerRegistryClient
ContainerRegistryClient client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential());

// Get the collection of repository names from the registry
Pageable<string> repositories = client.GetRepositoryNames();
foreach (string repository in repositories)
{
    Console.WriteLine(repository);
}

Listar marcas com acesso anônimo

// Get the service endpoint from the environment
Uri endpoint = new Uri(Environment.GetEnvironmentVariable("REGISTRY_ENDPOINT"));

// Create a new ContainerRegistryClient for anonymous access
ContainerRegistryClient client = new ContainerRegistryClient(endpoint);

// Obtain a RegistryArtifact object to get access to image operations
RegistryArtifact image = client.GetArtifact("library/hello-world", "latest");

// List the set of tags on the hello_world image tagged as "latest"
Pageable<ArtifactTagProperties> tags = image.GetAllTagProperties();

// Iterate through the image's tags, listing the tagged alias for the image
Console.WriteLine($"{image.FullyQualifiedReference} has the following aliases:");
foreach (ArtifactTagProperties tag in tags)
{
    Console.WriteLine($"    {image.RegistryEndpoint.Host}/{image.RepositoryName}:{tag}");
}

Definir propriedades do artefato

// Get the service endpoint from the environment
Uri endpoint = new Uri(Environment.GetEnvironmentVariable("REGISTRY_ENDPOINT"));

// Create a new ContainerRegistryClient and RegistryArtifact to access image operations
ContainerRegistryClient client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential());
RegistryArtifact image = client.GetArtifact("library/hello-world", "latest");

// Set permissions on the v1 image's "latest" tag
image.UpdateTagProperties("latest", new ArtifactTagProperties()
{
    CanWrite = false,
    CanDelete = false
});

Excluir imagens

// Get the service endpoint from the environment
Uri endpoint = new Uri(Environment.GetEnvironmentVariable("REGISTRY_ENDPOINT"));

// Create a new ContainerRegistryClient
ContainerRegistryClient client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential());

// Iterate through repositories
Pageable<string> repositoryNames = client.GetRepositoryNames();
foreach (string repositoryName in repositoryNames)
{
    ContainerRepository repository = client.GetRepository(repositoryName);

    // Obtain the images ordered from newest to oldest
    Pageable<ArtifactManifestProperties> imageManifests =
        repository.GetAllManifestProperties(manifestOrder: ArtifactManifestOrder.LastUpdatedOnDescending);

    // Delete images older than the first three.
    foreach (ArtifactManifestProperties imageManifest in imageManifests.Skip(3))
    {
        RegistryArtifact image = repository.GetArtifact(imageManifest.Digest);
        Console.WriteLine($"Deleting image with digest {imageManifest.Digest}.");
        Console.WriteLine($"   Deleting the following tags from the image: ");
        foreach (var tagName in imageManifest.Tags)
        {
            Console.WriteLine($"        {imageManifest.RepositoryName}:{tagName}");
            image.DeleteTag(tagName);
        }
        image.Delete();
    }
}

Listar repositórios de maneira assíncrona

As APIs assíncronas são idênticas aos respectivos equivalentes síncronos, mas os métodos terminam com o sufixo padrão "Assíncrono" do .NET e retornam uma Tarefa.

// Get the service endpoint from the environment
Uri endpoint = new Uri(Environment.GetEnvironmentVariable("REGISTRY_ENDPOINT"));

// Create a new ContainerRegistryClient
ContainerRegistryClient client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential());

// Get the collection of repository names from the registry
AsyncPageable<string> repositories = client.GetRepositoryNamesAsync();
await foreach (string repository in repositories)
{
    Console.WriteLine(repository);
}

Listar marcas com acesso anônimo de forma assíncrona

// Get the service endpoint from the environment
Uri endpoint = new Uri(Environment.GetEnvironmentVariable("REGISTRY_ENDPOINT"));

// Create a new ContainerRegistryClient for anonymous access
ContainerRegistryClient client = new ContainerRegistryClient(endpoint);

// Obtain a RegistryArtifact object to get access to image operations
RegistryArtifact image = client.GetArtifact("library/hello-world", "latest");

// List the set of tags on the hello_world image tagged as "latest"
AsyncPageable<ArtifactTagProperties> tags = image.GetAllTagPropertiesAsync();

// Iterate through the image's tags, listing the tagged alias for the image
Console.WriteLine($"{image.FullyQualifiedReference} has the following aliases:");
await foreach (ArtifactTagProperties tag in tags)
{
    Console.WriteLine($"    {image.RegistryEndpoint.Host}/{image.RepositoryName}:{tag}");
}

Definir propriedades do artefato de maneira assíncrona

// Get the service endpoint from the environment
Uri endpoint = new Uri(Environment.GetEnvironmentVariable("REGISTRY_ENDPOINT"));

// Create a new ContainerRegistryClient and RegistryArtifact to access image operations
ContainerRegistryClient client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential());
RegistryArtifact image = client.GetArtifact("library/hello-world", "v1");

// Set permissions on the image's "latest" tag
await image.UpdateTagPropertiesAsync("latest", new ArtifactTagProperties()
{
    CanWrite = false,
    CanDelete = false
});

Excluir imagens de maneira assíncrona

// Get the service endpoint from the environment
Uri endpoint = new Uri(Environment.GetEnvironmentVariable("REGISTRY_ENDPOINT"));

// Create a new ContainerRegistryClient
ContainerRegistryClient client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential());

// Iterate through repositories
AsyncPageable<string> repositoryNames = client.GetRepositoryNamesAsync();
await foreach (string repositoryName in repositoryNames)
{
    ContainerRepository repository = client.GetRepository(repositoryName);

    // Obtain the images ordered from newest to oldest
    AsyncPageable<ArtifactManifestProperties> imageManifests =
        repository.GetAllManifestPropertiesAsync(manifestOrder: ArtifactManifestOrder.LastUpdatedOnDescending);

    // Delete images older than the first three.
    await foreach (ArtifactManifestProperties imageManifest in imageManifests.Skip(3))
    {
        RegistryArtifact image = repository.GetArtifact(imageManifest.Digest);
        Console.WriteLine($"Deleting image with digest {imageManifest.Digest}.");
        Console.WriteLine($"   Deleting the following tags from the image: ");
        foreach (var tagName in imageManifest.Tags)
        {
            Console.WriteLine($"        {imageManifest.RepositoryName}:{tagName}");
            await image.DeleteTagAsync(tagName);
        }
        await image.DeleteAsync();
    }
}

Operações de blob e manifesto

Esta seção contém exemplos para ContainerRegistryContentClient que mostram como carregar e baixar imagens.

Primeiro, crie um cliente de blob.

// Get the service endpoint from the environment
Uri endpoint = new(Environment.GetEnvironmentVariable("REGISTRY_ENDPOINT"));

string repository = "sample-oci-image";
string tag = "demo";

// Create a new ContainerRegistryContentClient
ContainerRegistryContentClient client = new(endpoint, repository, new DefaultAzureCredential());

Carregar imagens

Para carregar uma imagem completa, precisamos carregar camadas e configurações individuais. Depois disso, podemos carregar um manifesto que descreve uma imagem ou artefato e atribuí-lo a uma marca.

// Create a manifest to list files in this image
OciImageManifest manifest = new(schemaVersion: 2);

// Upload a config file
BinaryData config = BinaryData.FromString("Sample config");
UploadRegistryBlobResult uploadConfigResult = await client.UploadBlobAsync(config);

// Update manifest with config info
manifest.Configuration = new OciDescriptor()
{
    Digest = uploadConfigResult.Digest,
    SizeInBytes = uploadConfigResult.SizeInBytes,
    MediaType = "application/vnd.oci.image.config.v1+json"
};

// Upload a layer file
BinaryData layer = BinaryData.FromString("Sample layer");
UploadRegistryBlobResult uploadLayerResult = await client.UploadBlobAsync(layer);

// Update manifest with layer info
manifest.Layers.Add(new OciDescriptor()
{
    Digest = uploadLayerResult.Digest,
    SizeInBytes = uploadLayerResult.SizeInBytes,
    MediaType = "application/vnd.oci.image.layer.v1.tar"
});

// Finally, upload the manifest file
await client.SetManifestAsync(manifest, tag);

Baixar imagens

Para baixar uma imagem completa, precisamos baixar seu manifesto e baixar camadas e configurações individuais.

// Download the manifest to obtain the list of files in the image
GetManifestResult result = await client.GetManifestAsync(tag);
OciImageManifest manifest = result.Manifest.ToObjectFromJson<OciImageManifest>();

string manifestFile = Path.Combine(path, "manifest.json");
using (FileStream stream = File.Create(manifestFile))
{
    await result.Manifest.ToStream().CopyToAsync(stream);
}

// Download and write out the config
DownloadRegistryBlobResult configBlob = await client.DownloadBlobContentAsync(manifest.Configuration.Digest);

string configFile = Path.Combine(path, "config.json");
using (FileStream stream = File.Create(configFile))
{
    await configBlob.Content.ToStream().CopyToAsync(stream);
}

// Download and write out the layers
foreach (OciDescriptor layerInfo in manifest.Layers)
{
    string layerFile = Path.Combine(path, TrimSha(layerInfo.Digest));
    using (FileStream stream = File.Create(layerFile))
    {
        await client.DownloadBlobToAsync(layerInfo.Digest, stream);
    }
}

static string TrimSha(string digest)
{
    int index = digest.IndexOf(':');
    if (index > -1)
    {
        return digest.Substring(index + 1);
    }

    return digest;
}

Excluir manifesto

GetManifestResult manifestResult = await client.GetManifestAsync(tag);
await client.DeleteManifestAsync(manifestResult.Digest);

Excluir Blob

GetManifestResult result = await client.GetManifestAsync(tag);
OciImageManifest manifest = result.Manifest.ToObjectFromJson<OciImageManifest>();

foreach (OciDescriptor layerInfo in manifest.Layers)
{
    await client.DeleteBlobAsync(layerInfo.Digest);
}

Autenticação avançada

Autenticar em uma nuvem nacional

Para autenticar com um registro em uma Nuvem Nacional, você precisará fazer as seguintes adições à configuração do cliente:

  • Defina o AuthorityHost nas opções de credencial ou por meio da AZURE_AUTHORITY_HOST variável de ambiente
  • Definir o Audience em ContainerRegistryClientOptions
// Create a ContainerRegistryClient that will authenticate through AAD in the China national cloud
Uri endpoint = new Uri(Environment.GetEnvironmentVariable("REGISTRY_ENDPOINT"));
ContainerRegistryClient client = new ContainerRegistryClient(endpoint,
    new DefaultAzureCredential(
        new DefaultAzureCredentialOptions()
        {
            AuthorityHost = AzureAuthorityHosts.AzureChina
        }),
    new ContainerRegistryClientOptions()
    {
        Audience = ContainerRegistryAudience.AzureChina
    });

Solução de problemas

Consulte nosso guia de solução de problemas para obter detalhes sobre como diagnosticar vários cenários de falha.

Próximas etapas

Contribuição

Este projeto aceita contribuições e sugestões. A maioria das contribuições exige que você concorde com um CLA (Contrato de Licença do Colaborador) declarando que você tem o direito de nos conceder, e de fato concede, os direitos de usar sua contribuição. Para obter detalhes, visite cla.microsoft.com.

Este projeto adotou o Código de Conduta de Software Livre da Microsoft. Para obter mais informações, confira as Perguntas frequentes sobre o Código de Conduta ou contate opencode@microsoft.com para enviar outras perguntas ou comentários.

Impressões