biblioteca cliente de Azure Container Registry para .NET: versión 1.1.0

Azure Container Registry permite almacenar y administrar imágenes y artefactos de contenedor en un registro privado para todos los tipos de implementaciones de contenedor.

Use la biblioteca cliente de Azure Container Registry para lo siguiente:

  • Enumeración de imágenes o artefactos en un registro
  • Obtención de metadatos para imágenes y artefactos, repositorios y etiquetas
  • Establecimiento de propiedades de lectura, escritura y eliminación en elementos del registro
  • Eliminación de imágenes y artefactos, repositorios y etiquetas

Código | fuente Paquete (NuGet) | Documentación | de referencia de API Documentación | de la API RESTDocumentación del producto

Introducción

Para desarrollar código de aplicación .NET que pueda conectarse a una instancia de Azure Container Registry, necesitará la biblioteca Azure.Containers.ContainerRegistry.

Instalar el paquete

Instale la biblioteca cliente de Azure Container Registry para .NET con NuGet:

dotnet add package Azure.Containers.ContainerRegistry

Requisitos previos

Necesitará una suscripción de Azure y una instancia de servicio de Container Registry para que la aplicación se conecte.

Para crear una instancia de Container Registry, puede usar Azure Portal, Azure PowerShell o la CLI de Azure. Este es un ejemplo de creación de un registro mediante la CLI de Azure:

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

Autenticar el cliente

Para que la aplicación se conecte al registro, deberá crear un cliente ContainerRegistryClient que pueda autenticarse con él. La biblioteca de identidades de Azure facilita la incorporación de compatibilidad con Azure Active Directory para autenticar clientes del SDK de Azure con sus servicios de Azure correspondientes.

Al desarrollar y depurar la aplicación localmente, puede usar su propio usuario para autenticarse en el registro. Una manera de hacerlo es autenticar el usuario con la CLI de Azure y ejecutar la aplicación desde este entorno. Si la aplicación usa un cliente que se ha construido para autenticarse con DefaultAzureCredential, se autenticará correctamente con el registro en el punto de conexión 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 el archivo Léame de identidad de Azure para obtener más enfoques para autenticarse con DefaultAzureCredential, tanto localmente como en entornos de implementación. Para conectarse a registros en nubes de Azure no públicas, consulte los ejemplos siguientes.

Para obtener más información sobre el uso de AAD con Azure Container Registry, consulte La información general sobre la autenticación del servicio.

Conceptos clave

Un registro almacena imágenes de Docker y artefactos de OCI. Una imagen o artefacto se compone de un manifiesto y capas. El manifiesto de una imagen describe las capas que componen la imagen y se identifica de forma única por su resumen. Una imagen también se puede "etiquetar" para darle un alias legible. Una imagen o artefacto puede tener cero o más etiquetas asociadas, y cada etiqueta identifica de forma única la imagen. Una colección de imágenes que comparten el mismo nombre, pero que tienen etiquetas diferentes, se conoce como repositorio.

Para más información, consulte Conceptos de Container Registry.

Seguridad para subprocesos

Garantizamos que todos los métodos de instancia de cliente son seguros para subprocesos e independientes entre sí (instrucciones). Esto garantiza que la recomendación de reutilizar instancias de cliente siempre es segura, incluso entre subprocesos.

Conceptos adicionales

Opciones | de cliente Acceso a la respuesta | Operaciones | de larga duraciónControl de errores | Diagnóstico | Burla | Duración del cliente

Ejemplos

Los fragmentos de código siguientes muestran breves ejemplos de escenarios comunes para desarrolladores mediante la biblioteca del SDK de ACR. Tenga en cuenta que cada ejemplo supone que hay una REGISTRY_ENDPOINT variable de entorno establecida en una cadena que contiene el https:// prefijo y el nombre del servidor de inicio de sesión, por ejemplo"https://myregistry.azurecr.io".

Ejemplos de sincronización

Ejemplos asincrónicos

Autenticación avanzada

Operaciones de registro

Este secion contiene ContainerRegistryClient ejemplos.

Lista de repositorios

Recorra en iteración la colección de repositorios del 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);
}

Enumerar etiquetas con acceso 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}");
}

Establecimiento de propiedades de artefactos

// 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
});

Eliminación de imágenes

// 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();
    }
}

Enumeración asincrónica de repositorios

Las API asincrónicas son idénticas a sus homólogos sincrónicos, pero los métodos terminan con el sufijo estándar de .NET "Async" y devuelven una tarea.

// 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);
}

Enumerar etiquetas con acceso anónimo de forma asincrónica

// 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}");
}

Establecimiento de propiedades de artefactos de forma asincrónica

// 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
});

Eliminación asincrónica de imágenes

// 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();
    }
}

Operaciones de blob y manifiesto

Esta sección contiene ejemplos para ContainerRegistryContentClient mostrar cómo cargar y descargar imágenes.

En primer lugar, cree un cliente de blobs.

// 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());

Carga de imágenes

Para cargar una imagen completa, es necesario cargar capas y configuraciones individuales. Después, podemos cargar un manifiesto que describa una imagen o artefacto y asígnele una etiqueta.

// 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);

Descargar imágenes

Para descargar una imagen completa, es necesario descargar su manifiesto y, a continuación, descargar capas individuales y configuración.

// 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;
}

Eliminar manifiesto

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

Eliminación de un blob

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

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

Autenticación avanzada

Autenticación en una nube nacional

Para autenticarse con un registro en una nube nacional, deberá realizar las siguientes adiciones a la configuración del cliente:

  • Establecimiento de AuthorityHost en las opciones de credenciales o a través de la variable de AZURE_AUTHORITY_HOST entorno
  • Establecer en AudienceContainerRegistryClientOptions
// 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
    });

Solución de problemas

Consulte nuestra guía de solución de problemas para obtener más información sobre cómo diagnosticar varios escenarios de error.

Pasos siguientes

Contribuciones

Este proyecto agradece las contribuciones y sugerencias. La mayoría de las contribuciones requieren que acepte un Contrato de licencia para el colaborador (CLA) que declara que tiene el derecho a concedernos y nos concede los derechos para usar su contribución. Para obtener más información, visite cla.microsoft.com.

Este proyecto ha adoptado el Código de conducta de Microsoft Open Source. Para más información, consulte las preguntas más frecuentes del código de conducta o póngase en contacto con opencode@microsoft.com si tiene cualquier otra pregunta o comentario.

Impresiones