Azure.Containers.ContainerRegistry
1.1.0
Prefix Reserved
See the version list below for details.
dotnet add package Azure.Containers.ContainerRegistry --version 1.1.0
NuGet\Install-Package Azure.Containers.ContainerRegistry -Version 1.1.0
<PackageReference Include="Azure.Containers.ContainerRegistry" Version="1.1.0" />
paket add Azure.Containers.ContainerRegistry --version 1.1.0
#r "nuget: Azure.Containers.ContainerRegistry, 1.1.0"
// Install Azure.Containers.ContainerRegistry as a Cake Addin #addin nuget:?package=Azure.Containers.ContainerRegistry&version=1.1.0 // Install Azure.Containers.ContainerRegistry as a Cake Tool #tool nuget:?package=Azure.Containers.ContainerRegistry&version=1.1.0
Azure Container Registry client library for .NET
Azure Container Registry allows you to store and manage container images and artifacts in a private registry for all types of container deployments.
Use the client library for Azure Container Registry to:
- List images or artifacts in a registry
- Obtain metadata for images and artifacts, repositories and tags
- Set read/write/delete properties on registry items
- Delete images and artifacts, repositories and tags
Source code | Package (NuGet) | API reference documentation | REST API documentation | Product documentation
Getting started
To develop .NET application code that can connect to an Azure Container Registry instance, you will need the Azure.Containers.ContainerRegistry
library.
Install the package
Install the Azure Container Registry client library for .NET with NuGet:
dotnet add package Azure.Containers.ContainerRegistry
Prerequisites
You will need an Azure subscription and a Container Registry service instance for your application to connect to.
To create a new Container Registry, you can use the Azure Portal, Azure PowerShell, or the Azure CLI. Here'a an example of creating a new registry using the Azure CLI:
az acr create --name myregistry --resource-group myresourcegroup --location westus --sku Basic
Authenticate the client
For your application to connect to your registry, you'll need to create a ContainerRegistryClient
that can authenticate with it. The Azure Identity library makes it easy to add Azure Active Directory support for authenticating Azure SDK clients with their corresponding Azure services.
When you're developing and debugging your application locally, you can use your own user to authenticate with your registry. One way to accomplish this is to authenticate your user with the Azure CLI and run your application from this environment. If your application is using a client that has been constructed to authenticate with DefaultAzureCredential
, it will correctly authenticate with the registry at the specified endpoint.
// 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
});
Please see the Azure Identity README for more approaches to authenticating with DefaultAzureCredential
, both locally and in deployment environments. To connect to registries in non-public Azure Clouds, see the samples below.
For more information on using AAD with Azure Container Registry, please see the service's Authentication Overview.
Key concepts
A registry stores Docker images and OCI Artifacts. An image or artifact consists of a manifest and layers. An image's manifest describes the layers that make up the image, and is uniquely identified by its digest. An image can also be "tagged" to give it a human-readable alias. An image or artifact can have zero or more tags associated with it, and each tag uniquely identifies the image. A collection of images that share the same name but have different tags, is referred to as a repository.
For more information please see Container Registry Concepts.
Thread safety
We guarantee that all client instance methods are thread-safe and independent of each other (guideline). This ensures that the recommendation to reuse client instances is always safe, even across threads.
Additional concepts
Client options | Accessing the response | Long-running operations | Handling failures | Diagnostics | Mocking | Client lifetime
Examples
The following snippets show brief samples of common developer scenarios using the ACR SDK library.
Please note that each sample assumes there is a REGISTRY_ENDPOINT
environment variable set to a string containing the https://
prefix and the name of the login server, for example "https://myregistry.azurecr.io".
Sync examples
- Registry operations:
Async examples
- Registry operations:
- Blob and manifest operations:
Advanced authentication
Registry operations
This secion contains ContainerRegistryClient
samples.
List repositories
Iterate through the collection of repositories in the registry.
// 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);
}
List tags with anonymous access
// 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}");
}
Set artifact properties
// 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
});
Delete images
// 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();
}
}
List repositories asynchronously
The asynchronous APIs are identical to their synchronous counterparts, but methods end with the standard .NET "Async" suffix and return a Task.
// 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);
}
List tags with anonymous access asynchronously
// 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}");
}
Set artifact properties asynchronously
// 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
});
Delete images asynchronously
// 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();
}
}
Blob and manifest operations
This section contains samples for ContainerRegistryContentClient
that show how to upload and download images.
First, create a blob client.
// 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());
Upload images
To upload a full image, we need to upload individual layers and configuration. After that we can upload a manifest which describes an image or artifact and assign it a tag.
// 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);
Download images
To download a full image, we need to download its manifest and then download individual layers and configuration.
// 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;
}
Delete manifest
GetManifestResult manifestResult = await client.GetManifestAsync(tag);
await client.DeleteManifestAsync(manifestResult.Digest);
Delete blob
GetManifestResult result = await client.GetManifestAsync(tag);
OciImageManifest manifest = result.Manifest.ToObjectFromJson<OciImageManifest>();
foreach (OciDescriptor layerInfo in manifest.Layers)
{
await client.DeleteBlobAsync(layerInfo.Digest);
}
Advanced authentication
Authenticate in a National Cloud
To authenticate with a registry in a National Cloud, you will need to make the following additions to your client configuration:
- Set the
AuthorityHost
in the credential options or via theAZURE_AUTHORITY_HOST
environment variable - Set the
Audience
inContainerRegistryClientOptions
// 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
});
Troubleshooting
See our troubleshooting guide for details on how to diagnose various failure scenarios.
Next steps
- Go further with Azure.Containers.ContainerRegistry and our samples.
- Watch a demo or deep dive video.
- Read more about the Azure Container Registry service.
Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit cla.microsoft.com.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Azure.Core (>= 1.32.0)
- System.Text.Json (>= 4.7.2)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on Azure.Containers.ContainerRegistry:
Package | Downloads |
---|---|
Azure.Bicep.Core
Bicep compiler core functionality. The Bicep team has made this NuGet package publicly available on nuget.org. While it is public, it is not a supported package. Any dependency you take on this package will be done at your own risk and we reserve the right to push breaking changes to this package at any time. |
|
CasCap.Apis.Azure.ContainerRegistry
Helper library for Azure Container Registry. |
|
CodeOps.InfrastructureAsCode.Azure.ContainerRegistry
CodeOps.InfrastructureAsCode.Azure.ContainerRegistry |
|
CasCap.Api.Azure.ContainerRegistry
Helper library for Azure Container Registry. |
GitHub repositories (2)
Showing the top 2 popular GitHub repositories that depend on Azure.Containers.ContainerRegistry:
Repository | Stars |
---|---|
Azure/azure-powershell
Microsoft Azure PowerShell
|
|
dotnet/docker-tools
This is a repo to house some common tools for our various docker repos.
|
Version | Downloads | Last updated |
---|---|---|
1.2.0-beta.1 | 8,382 | 7/12/2023 |
1.1.1 | 437,598 | 12/13/2023 |
1.1.0 | 523,710 | 5/11/2023 |
1.1.0-beta.9 | 75,341 | 4/11/2023 |
1.1.0-beta.8 | 35,613 | 3/14/2023 |
1.1.0-beta.7 | 183 | 3/7/2023 |
1.1.0-beta.6 | 8,748 | 2/7/2023 |
1.1.0-beta.5 | 5,831 | 1/11/2023 |
1.1.0-beta.4 | 211,072 | 4/6/2022 |
1.1.0-beta.3 | 59,108 | 11/10/2021 |
1.1.0-beta.2 | 3,818 | 10/25/2021 |
1.1.0-beta.1 | 5,532 | 9/7/2021 |
1.0.0 | 174,551 | 1/14/2022 |
1.0.0-beta.5 | 3,964 | 11/18/2021 |
1.0.0-beta.4 | 452 | 8/10/2021 |
1.0.0-beta.3 | 1,038 | 6/8/2021 |
1.0.0-beta.2 | 1,084 | 5/11/2021 |
1.0.0-beta.1 | 1,921 | 4/8/2021 |