New features added in the Azure Container Registry PowerShell module
Published Apr 13 2021 08:20 AM 5,677 Views
Microsoft

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.

 

ACR overview

The graph below shows resources and the structure under an Azure container registry. We’ll dive into more details later in this article.

YaboHu_0-1617936659735.png

 

Authentication

 
 

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

 

 

Repositories

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:

  • acr-helloworld:latest
  • acr-helloworld:v1
  • acr-helloworld:v2

 

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

 

 

Images

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

  • manifest
  • $repository_name:$tag

Manifest

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

 

 

Tag

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.

 

Performance

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

 

 

Conclusion & Feedback

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

Co-Authors
Version history
Last update:
‎Apr 08 2021 08:37 PM
Updated by: