├── Dockerfile ├── acr-cleanup.ps1 └── readme.md /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/azure-cli 2 | 3 | ADD acr-cleanup.ps1 / 4 | 5 | RUN mkdir /opt/powershell \ 6 | && wget https://github.com/PowerShell/PowerShell/releases/download/v7.0.3/powershell-7.0.3-linux-alpine-x64.tar.gz -O - | tar -xz -C /opt/powershell \ 7 | && ln -s /opt/powershell/pwsh /usr/local/bin 8 | 9 | -------------------------------------------------------------------------------- /acr-cleanup.ps1: -------------------------------------------------------------------------------- 1 | # This script check and removes the old docker images from the azure container registry 2 | # WARNING: this script will delete all image tags within a repository that share the same manifest 3 | 4 | [CmdletBinding()] 5 | Param( 6 | # Define ACR Name 7 | [Parameter (Mandatory=$true)] 8 | [ValidateNotNullOrEmpty()] 9 | [String] $AzureRegistryName, 10 | 11 | # Define Azure Subscription Name 12 | [Parameter (Mandatory=$false)] 13 | [ValidateNotNullOrEmpty()] 14 | [String] $SubscriptionName, 15 | 16 | # Number of images to retain per respository 17 | [Parameter (Mandatory=$false)] 18 | [ValidateNotNullOrEmpty()] 19 | [Int] $ImagestoKeep = 10, 20 | 21 | # Enable deletion or just run in scan mode 22 | [Parameter (Mandatory=$false)] 23 | [ValidateNotNullOrEmpty()] 24 | [String] $EnableDelete = "no", 25 | 26 | # Specify repository to cleanup (if not specified will default to all repositories within the registry) 27 | [Parameter (Mandatory=$false)] 28 | [ValidateNotNullOrEmpty()] 29 | [String] $Repository 30 | ) 31 | 32 | $imagesDeleted = 0 33 | 34 | if ($SubscriptionName){ 35 | Write-Host "Setting subscription to: $SubscriptionName" 36 | az account set --subscription $SubscriptionName 37 | } 38 | 39 | if ($Repository){ 40 | $RepoList = @("", "", $Repository) 41 | } 42 | else { 43 | Write-Host "Getting list of all repositories in container registry: $AzureRegistryName" 44 | $RepoList = az acr repository list --name $AzureRegistryName --output table 45 | } 46 | 47 | for($index=2; $index -lt $RepoList.length; $index++){ 48 | $RepositoryName = $RepoList[$index] 49 | 50 | write-host "" 51 | Write-Host "Checking repository: $RepositoryName" 52 | $RepositoryTags = az acr repository show-tags --name $AzureRegistryName --repository $RepositoryName --output tsv --orderby time_desc 53 | write-host "# Total images:"$RepositoryTags.length" # Images to keep:"$ImagestoKeep 54 | 55 | if ($RepositoryTags.length -gt $ImagestoKeep) { 56 | write-host "Deleting surplus images..." 57 | for ($item=$ImagestoKeep; $item -lt $RepositoryTags.length; $item++) { 58 | $ImageName = $RepositoryName + ":" + $RepositoryTags[$item] 59 | $imagesDeleted++ 60 | if ($EnableDelete -eq "yes") { 61 | write-host "deleting:"$ImageName 62 | az acr repository delete --name $AzureRegistryName --image $ImageName --yes 63 | } 64 | else { 65 | write-host "dummy delete:"$ImageName 66 | } 67 | } 68 | } 69 | else { 70 | write-host "No surplus images to delete." 71 | } 72 | } 73 | 74 | write-host "" 75 | Write-Host "ACR cleanup completed" 76 | write-host "Total images deleted:"$imagesDeleted -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Azure Container Registry Cleanup 2 | To maintain the size of your Azure Container Registry you should regularly delete old images. This script leverages Azure's **az acr repository** command to scan for and delete surplus images. 3 | 4 | An example of where this script is useful is where multiple images are created during a continuous integration (CI) process. 5 | 6 | Depending on the parameters used it's possible to define the number of images to retain per registry. For example you may wish to retain the 10 most recent images. 7 | 8 | *** WARNING: this script deletes the manifest referenced by the image tag and all other tags referencing the manifest. As long as each tag has a unique manifest this won't be an issue. Please run with EnableDelete=no initially to test the behaviour against your container registry *** 9 | 10 | ## Getting Started 11 | These instructions will allow you to run the PowerShell script. The script can either be run locally or in Azure Cloud Shell. 12 | 13 | ## Prerequisites 14 | * You need to have Azure CLI and PowerShell installed on the machine, where you are running the script 15 | * Before running the script ensure you're logged into Azure using the **az login** cmdlet 16 | 17 | ## Parameters 18 | * **AzureRegistryName** (required) - provide the name of the target Azure Container Registry 19 | * **SubscriptionName** (optional) - if login is associated with only one subscription, then you do not need to provide this. If not, this can be used to set the context in which container registry is located 20 | * **Repository** (optional) - specify the repository to scan for surplus images to delete. If omitted all repositories will be be scanned within the specified container registry 21 | * **ImagestoKeep** (optional) - the number of images per repository to retain (default = 10) 22 | * **EnableDelete** (optional) - enable actual deletion of images instead of just scanning for surplus images (default = no, change to "yes" to delete images) 23 | 24 | 25 | ## Examples 26 | * Example 1: **.\acr-cleanup.ps1 -azureregistryname yourregistryname** 27 | 28 | In this case, script will default to scanning for images to delete (ImagestoKeep = 10 and EnableDelete = "no") 29 | 30 | * Example 2: **.\acr-cleanup.ps1 -azureregistryname yourregistryname -enabledelete yes** 31 | 32 | In this case, script will delete any surplus images above the default of 10 images 33 | 34 | * Example 3: **.\acr-cleanup.ps1 -azureregistryname yourregistryname -enabledelete yes -imagestokeep 20** 35 | 36 | In this case, script will delete any surplus images above 20 images per repository 37 | 38 | * Example 4: **.\acr-cleanup.ps1 -azureregistryname yourregistryname -enabledelete yes -repository yourrepositoryname** 39 | 40 | In this case, script will delete any surplus images within the "yourrepositoryname" repository 41 | 42 | ## Dockerfile 43 | Add a Dockerfile to build and run this script inside a Docker container. We use the Azure CLI container and pull in the Power Shell cross platform binaries. 44 | --------------------------------------------------------------------------------