While Azure Container Registry (ACR) is prevalent as an Azure service, the corresponding Az.ContainerRegistry Azure PowerShell module wasn’t fully featured. Sometimes, PowerShell users had to take advantage of the Az CLI. We want to allow PowerShell user to be able to fully manage container images. Starting with Az.ContainerRegistry version 2.2.1, we will gradually be rolling out new cmdlets and new parameters. In this release, you can now fully manage (Get-, Remove-, Update-) repositories, manifests, and tags with increased performance.
The graph below shows resources and the structure under an Azure container registry. We’ll dive into more details later in this article.
After login into your Azure account in Azure-PowerShell with
PS:> Connect-AzAccount
You can now simply run
PS:> Connect-AzContainerRegistry -Name $RegistryName
Alternatively, you can also use service principal authentication
PS:> Connect-AzContainerRegistry -Name $RegistryName -UserName $ApplicationId -Password $ClientSecret
If you happened to have the registry admin user enabled
PS:> $secret = Get-AzContainerRegistryCredential -ResourceGroupName $RGName -Name $RegistryName
PS:> Connect-AzContainerRegistry -Name $RegistryName
-UserName $secret.UserName
-Password $secret.Password
A repository is a collection of container images or other artifacts in a registry that have the same name, but different tags. For example, the following three images are in the acr-helloworld repository:
A JSON format repository could look like the following
{
"registry": "xxx.azurecr.io",
"imageName": "test/busybox",
"createdTime": "2021-02-02T04:11:14.4504049Z",
"lastUpdateTime": "2021-02-02T05:02:14.2671834Z",
"manifestCount": 1,
"tagCount": 150,
"changeableAttributes": {
"deleteEnabled": true,
"writeEnabled": true,
"readEnabled": true,
"listEnabled": true
}
To get repositories via Az.ContainerRegistry
PS:> $repository = Get-AzContainerRegistryRepository -RegistryName xxx -Name test/busybox
PS:> $repository
Registry : xxx.azurecr.io
ImageName : test/busybox
CreatedTime : 2021-02-02T04:11:14.4504049Z
LastUpdateTime : 2021-02-02T05:02:14.2671834Z
ManifestCount : 1
TagCount : 150
ChangeableAttributes : Microsoft.Azure.Commands.ContainerRegistry.Models.PSChangeableAttribute
PS:> $repository.ChangeableAttributes | ft
DeleteEnabled WriteEnabled ListEnabled ReadEnabled
------------- ------------ ----------- -----------
True True True True
You can also list all repository names under your registry
PS:> Get-AzContainerRegistryRepository -RegistryName xxx
alpine
test/busybox
test/busybox1
test/busybox10
test/busybox11
test/busybox12
To delete an existing repository
PS:> Update-AzContainerRegistryRepository -RegistryName xxx -Name test/busybox -DeleteEnabled $true
PS:> Remove- AzContainerRegistryRepository -RegistryName xxx -Name test/busybox
Grouped in a repository, each image or artifact is a read-only multi-layer snapshot of a Docker-compatible container.
An artifact can be represented as either one of
Each image or other artifact pushed to a registry is associated with a JSON format manifest. The manifest, generated by the registry when the content is pushed, uniquely identifies the artifact.
"manifests": [
{
"digest": "sha256:31a54a0cf86d7354788a8265f60ae6acb4b348a67efbcf7c1007dd3cf7af05ab",
"imageSize": 764633,
"createdTime": "2020-12-11T09:17:20.4959715Z",
"lastUpdateTime": "2020-12-11T09:17:20.4959715Z",
"architecture": "amd64",
"os": "linux",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"configMediaType": "application/vnd.docker.container.image.v1+json",
"tags": [
"latest"
],
"changeableAttributes": {
"deleteEnabled": false,
"writeEnabled": true,
"readEnabled": true,
"listEnabled": true
}
}
Manifests are identified by a unique SHA-256 hash, manifest digest. Each image or artifact, whether tagged or not, is identified by its digest. The digest value is unique even if the artifact's layer data is identical to that of another artifact. This mechanism is what allows you to repeatedly push identically tagged images to a registry. For example, you can repeatedly push “myimage:latest” to your registry without error because each image is identified by its unique digest.
Similarly, to get, list, update, or remove a manifest under a repository
PS:> Get-AzContainerRegistryManifest -RegistryName xxx
-RepositoryName test/busybox50
-Name sha256:31a54a0cf86d7354788a8265f60ae6acb4b348a67efbcf7c1007dd3cf7af05ab
Registry : xxx.azurecr.io
ImageName : test/busybox50
Attributes : Microsoft.Azure.Commands.ContainerRegistry.Models.PSManifestAttributeBase
PS:> Get-AzContainerRegistryManifest -RegistryName xxx -RepositoryName test/busybox50
PS:> Update-AzContainerRegistryManifest -RegistryName xxx
-RepositoryName test/busybox50
-Manifest sha256:31a54a0cf86d7354788a8265f60ae6acb4b348a67efbcf7c1007dd3cf7af05ab
-DeleteEnabled $true
PS:> Remove-AzContainerRegistryManifest -RegistryName xxx
-RepositoryName test/busybox50
-Manifest sha256:31a54a0cf86d7354788a8265f60ae6acb4b348a67efbcf7c1007dd3cf7af05ab
Please be aware that to delete a repository, all manifests under it should have
"deleteEnabled": true
Tags for an image or other artifact specifies its version. A single artifact within a repository can be assigned one or many tags, this artifact may also be "untagged." That is, you can delete all tags from an image, while the image's data (its layers) remain in the registry.
"tag": {
"name": "latest",
"digest": "sha256:31a54a0cf86d7354788a8265f60ae6acb4b348a67efbcf7c1007dd3cf7af05ab",
"createdTime": "2020-12-11T09:17:20.6865195Z",
"lastUpdateTime": "2020-12-11T09:17:20.6865195Z",
"signed": false,
"changeableAttributes": {
"deleteEnabled": true,
"writeEnabled": true,
"readEnabled": true,
"listEnabled": true
}
}
The repository plus a tag defines an image name. You can push and pull an image by specifying its name in the push or pull operation. The tag latest is used by default if you don't provide one in your Docker commands. As you can see in the ACR Overview section, “repository3:latest” and “repository3:v2” both represent the same image “artifact3”.
Similarly, to get, list, update, or remove a tag for one artifact
PS:> Get-AzContainerRegistryTag -RegistryName xxx
-RepositoryName test/busybox50
-Name latest
Registry : xxx.azurecr.io
ImageName : test/busybox50
Attributes : Microsoft.Azure.Commands.ContainerRegistry.Models.PSTagAttributeBase
PS:> Get-AzContainerRegistryTag -RegistryName xxx -RepositoryName test/busybox50
PS:> Update-AzContainerRegistryTag -RegistryName xxx
-RepositoryName test/busybox50
-Name latest
-DeleteEnabled $true
Notice that after
PS:> Remove-AzContainerRegistryTag -RegistryName xxx
-RepositoryName test/busybox50
-Name latest
The tag “latest” was removed (untagged), means you cannot find
“test/busybox50:latest”. In this repository anymore, but the corresponding artifact remained (get manifest)
PS:> $digest = (Get-AzContainerRegistryTag -RegistryName xxx
-RepositoryName test/busybox50
-Name latest). Attributes.Digest
PS:> Get-AzContainerRegistryManifest -RegistryName xxx
-RepositoryName test/busybox50
-Name $digest
Registry : xxx.azurecr.io
ImageName : test/busybox50
Attributes : Microsoft.Azure.Commands.ContainerRegistry.Models.PSManifestAttributeBase
It’s also possible to update or delete a manifest by tag, it’s easier since it’s more recognizable to use a meaningful tag than series SHA256 hash code
PS:> Update-AzContainerRegistryManifest -RegistryName xxx
-RepositoryName test/busybox50
-Tag latest
-DeleteEnabled $true
PS:> Remove-AzContainerRegistryManifest -RegistryName xxx
-RepositoryName test/busybox50
-Tag latest
In this way, not only the tag, but the artifact itself would also be deleted.
We found there are performance issues in each repository, manifest, and tag manipulating operation. They were all relatively slow because ACR categorized each operation with different scopes.
A typical scope is in below format:
“$resource_type:$resource_name:$permission”
For example, to list all tags under repository “alpine”, the scope for this operation would be
“repository:alpine:metadata_read”
The specific token required for this request is assigned based on the exact scope.
For these kinds of operations, there will be 2 more extra HTTP requests sent out for token exchange before your actual operation.
HTTP Method:
POST
Absolute Uri:
https://xxx.azurecr.io/oauth2/token
HTTP Method:
POST
Absolute Uri:
https://xxx.azurecr.io/oauth2/Exchange
To reduce these costly requests, we implemented a token cache in your current PowerShell session, it will cache all ACR tokens. For operations that used existing tokens (operations with same scope), the previously referenced token exchange won’t happen until tokens in the cache expire. For repetitive operations, the total number of requests is now only one instead of three.
You can clear this token cache in your current PowerShell session by running
PS:> Clear-AzContext
This cmdlet also terminates the login state for Azure. Remember to re-connect.
PS:> Connect-AzAccount
With these features added, Az.ContainerRegistry is now much more usable. It's highly recommended to download the latest module at
https://www.powershellgallery.com/packages?q=az.containerregistry
and give a shot.
We also look forward to your feedback. Report issues at:
https://github.com/Azure/azure-powershell/issues
Yabo Hu
Software Engineer
Azure-PowerShell Team
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.