mirror of
https://github.com/github/awesome-copilot.git
synced 2026-08-17 14:46:56 +00:00
Add azure-container-registry-cli skill (#2450)
* Add azure-container-registry-cli skill * Address Copilot review: 2025 ACR changes (ABAC, zone redundancy, task network bypass) and secure credential handling * Add ACI (Azure Container Instances) to codespell ignore list * Address second Copilot review wave: DCT deprecation, purge --untagged caveat, soft-delete tiers, Catalog Lister scope, secret quoting --------- Co-authored-by: Aaron Powell <me@aaron-powell.com>
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
# Images & Artifacts
|
||||
|
||||
## Table of Contents
|
||||
- [Import Images (Server-Side Copy)](#import-images-server-side-copy)
|
||||
- [Repositories & Tags](#repositories--tags)
|
||||
- [Manifests](#manifests)
|
||||
- [Untag vs Delete](#untag-vs-delete)
|
||||
- [Purge Old Images (acr purge)](#purge-old-images-acr-purge)
|
||||
- [Lock Images](#lock-images)
|
||||
- [Retention Policy & Soft Delete](#retention-policy--soft-delete)
|
||||
- [Artifact Cache (Pull-Through Cache)](#artifact-cache-pull-through-cache)
|
||||
- [Storage Usage](#storage-usage)
|
||||
|
||||
---
|
||||
|
||||
## Import Images (Server-Side Copy)
|
||||
|
||||
Preferred over `docker pull` + `docker push` — no local storage, keeps multi-arch manifests intact:
|
||||
|
||||
```bash
|
||||
# From a public registry
|
||||
az acr import --name {registry} --source mcr.microsoft.com/hello-world:latest
|
||||
az acr import --name {registry} --source docker.io/library/nginx:1.27 --image nginx:1.27
|
||||
|
||||
# From another ACR in the same tenant (by resource ID, no credentials needed)
|
||||
az acr import --name {registry} \
|
||||
--source app:v1 \
|
||||
--registry /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.ContainerRegistry/registries/{src-registry}
|
||||
|
||||
# From a private registry with credentials
|
||||
az acr import --name {registry} --source private.example.com/app:v1 \
|
||||
--username {user} --password {password}
|
||||
|
||||
# Overwrite an existing tag
|
||||
az acr import --name {registry} --source docker.io/library/nginx:1.27 --image nginx:1.27 --force
|
||||
```
|
||||
|
||||
## Repositories & Tags
|
||||
|
||||
```bash
|
||||
az acr repository list --name {registry} --output table
|
||||
|
||||
# Tags, newest first, with digest and timestamps
|
||||
az acr repository show-tags --name {registry} --repository app \
|
||||
--orderby time_desc --detail --output table
|
||||
|
||||
az acr repository show --name {registry} --image app:v1 # tag attributes
|
||||
az acr repository show --name {registry} --repository app # repo attributes
|
||||
```
|
||||
|
||||
## Manifests
|
||||
|
||||
```bash
|
||||
# Metadata for all manifests in a repo (digest, tags, size, timestamps)
|
||||
az acr manifest list-metadata --registry {registry} --name app --output table
|
||||
|
||||
# One manifest's metadata / raw content
|
||||
az acr manifest show-metadata --registry {registry} --name app:v1
|
||||
az acr manifest show --registry {registry} --name app@sha256:{digest}
|
||||
|
||||
# Find untagged (orphaned) manifests
|
||||
az acr manifest list-metadata --registry {registry} --name app \
|
||||
--query "[?tags==null].digest" --output tsv
|
||||
```
|
||||
|
||||
## Untag vs Delete
|
||||
|
||||
```bash
|
||||
# Untag: removes only the tag; manifest + layers remain (still pullable by digest)
|
||||
az acr repository untag --name {registry} --image app:v1
|
||||
|
||||
# Delete by tag: deletes the whole manifest and ALL other tags pointing to it
|
||||
az acr repository delete --name {registry} --image app:v1 --yes
|
||||
|
||||
# Delete by digest (precise)
|
||||
az acr repository delete --name {registry} --image app@sha256:{digest} --yes
|
||||
|
||||
# Delete an entire repository
|
||||
az acr repository delete --name {registry} --repository app --yes
|
||||
```
|
||||
|
||||
⚠️ Deleting by tag deletes the underlying manifest — other tags on the same image disappear too. Untag first if you only want to retire a tag name.
|
||||
|
||||
## Purge Old Images (acr purge)
|
||||
|
||||
`acr purge` runs as an ACR Task (container `mcr.microsoft.com/acr/acr-cli`):
|
||||
|
||||
```bash
|
||||
# Dry run first — ALWAYS
|
||||
az acr run --registry {registry} \
|
||||
--cmd "acr purge --filter 'app:.*' --ago 30d --untagged --dry-run" /dev/null
|
||||
|
||||
# Delete tags older than 30 days matching the regex, plus untagged manifests
|
||||
az acr run --registry {registry} \
|
||||
--cmd "acr purge --filter 'app:.*' --ago 30d --untagged" /dev/null
|
||||
|
||||
# Keep the 5 most recent tags regardless of age
|
||||
az acr run --registry {registry} \
|
||||
--cmd "acr purge --filter 'app:.*' --ago 0d --keep 5 --untagged" /dev/null
|
||||
|
||||
# Schedule as a nightly task
|
||||
az acr task create --registry {registry} --name purge-old-images \
|
||||
--cmd "acr purge --filter 'app:.*' --ago 30d --untagged" \
|
||||
--context /dev/null --schedule "0 3 * * *"
|
||||
```
|
||||
|
||||
`--filter` takes `repository:tag-regex` and can be repeated for multiple repos.
|
||||
|
||||
⚠️ `--untagged` ignores `--ago`: it deletes **every** untagged manifest, including ones created moments ago (mid-push images, referrer artifacts). Omit `--untagged` if recent untagged manifests must survive — the age cutoff only applies to tagged images matched by `--filter`.
|
||||
|
||||
## Lock Images
|
||||
|
||||
Prevent overwrite or deletion of critical tags (e.g., released versions):
|
||||
|
||||
```bash
|
||||
# Read-only: cannot be overwritten or deleted
|
||||
az acr repository update --name {registry} --image app:v1 --write-enabled false
|
||||
|
||||
# Undeletable but still overwritable
|
||||
az acr repository update --name {registry} --image app:v1 --delete-enabled false
|
||||
|
||||
# Unlock
|
||||
az acr repository update --name {registry} --image app:v1 --write-enabled true --delete-enabled true
|
||||
```
|
||||
|
||||
## Retention Policy & Soft Delete
|
||||
|
||||
Two distinct policies that **cannot be enabled at the same time**. Retention policy requires **Premium**; soft delete (preview) is available in **all tiers** but doesn't support geo-replicated or artifact-cache-enabled registries.
|
||||
|
||||
```bash
|
||||
# Retention policy (Premium): auto-delete untagged manifests after N days (0 = immediately)
|
||||
az acr config retention update --registry {registry} \
|
||||
--status enabled --days 7 --type UntaggedManifests
|
||||
az acr config retention show --registry {registry}
|
||||
|
||||
# Soft delete (preview, all tiers): recover deleted artifacts within 1-90 days
|
||||
az acr config soft-delete update --registry {registry} --status enabled --days 7
|
||||
az acr repository list-deleted --name {registry}
|
||||
az acr manifest restore --registry {registry} --name app:v1
|
||||
```
|
||||
|
||||
## Artifact Cache (Pull-Through Cache)
|
||||
|
||||
Cache upstream images (Docker Hub, MCR, GHCR, quay.io, ECR Public) in your registry — avoids rate limits and centralizes provenance:
|
||||
|
||||
```bash
|
||||
# Optional: credentials for authenticated upstream (secrets live in Key Vault)
|
||||
az acr credential-set create --registry {registry} --name dockerhub-creds \
|
||||
--login-server docker.io \
|
||||
--username-id https://{vault}.vault.azure.net/secrets/dh-user \
|
||||
--password-id https://{vault}.vault.azure.net/secrets/dh-pass
|
||||
|
||||
# Cache rule: docker.io/library/* -> {registry}.azurecr.io/dockerhub/*
|
||||
az acr cache create --registry {registry} --name dockerhub-cache \
|
||||
--source-repo "docker.io/library/*" --target-repo "dockerhub/*" \
|
||||
--cred-set dockerhub-creds
|
||||
|
||||
az acr cache list --registry {registry} --output table
|
||||
```
|
||||
|
||||
Then `docker pull {registry}.azurecr.io/dockerhub/nginx:1.27` fetches through the cache.
|
||||
|
||||
## Storage Usage
|
||||
|
||||
```bash
|
||||
# Consumed storage vs SKU quota (Basic 10 GB / Standard 100 GB / Premium 500 GB included)
|
||||
az acr show-usage --name {registry} --output table
|
||||
```
|
||||
|
||||
Layers are deduplicated and shared across repositories; `show-usage` reports actual billable storage.
|
||||
Reference in New Issue
Block a user