-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Add azure-container-registry-cli skill #2450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
aaronpowell
merged 6 commits into
github:main
from
AClerbois:feature/azure-container-registry-cli-skill
Jul 30, 2026
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
785e2f9
Add azure-container-registry-cli skill
AClerbois 1851a92
Address Copilot review: 2025 ACR changes (ABAC, zone redundancy, task…
AClerbois 723924b
Merge branch 'main' into feature/azure-container-registry-cli-skill
aaronpowell 50991e6
Add ACI (Azure Container Instances) to codespell ignore list
AClerbois 569215d
Address second Copilot review wave: DCT deprecation, purge --untagged…
AClerbois ec1f0be
Merge branch 'main' into feature/azure-container-registry-cli-skill
AClerbois File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| --- | ||
| name: azure-container-registry-cli | ||
| description: 'Manage Azure Container Registry via the az acr CLI including registries, images, cloud builds, ACR Tasks, authentication, tokens, geo-replication, and networking. Use when working with ACR, az acr commands, pushing/importing/purging container images in Azure, or when the user mentions Azure Container Registry.' | ||
| --- | ||
|
|
||
| # Azure Container Registry CLI | ||
|
|
||
| Manage Azure Container Registry (ACR) resources using the `az acr` command group of the Azure CLI. | ||
|
|
||
| **CLI:** `az acr` ships with core Azure CLI — no extension required (the `acrtransfer` extension is only needed for export/import pipelines). | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| ```bash | ||
| # Install Azure CLI | ||
| brew install azure-cli # macOS | ||
| curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash # Linux | ||
| winget install Microsoft.AzureCLI # Windows | ||
|
|
||
| # Sign in and select subscription | ||
| az login | ||
| az account set --subscription {subscription-id} | ||
| ``` | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ```bash | ||
| # Create a registry (SKU: Basic | Standard | Premium) | ||
| az acr create --resource-group {rg} --name {registry} --sku Standard | ||
|
|
||
| # Authenticate Docker/Podman against the registry | ||
| az acr login --name {registry} | ||
|
|
||
| # Build and push in the cloud — no local Docker needed | ||
| az acr build --registry {registry} --image app:v1 . | ||
|
|
||
| # Copy an image from another registry without pull/push | ||
| az acr import --name {registry} --source mcr.microsoft.com/hello-world:latest | ||
|
|
||
| # List repositories and tags | ||
| az acr repository list --name {registry} --output table | ||
| az acr repository show-tags --name {registry} --repository app --orderby time_desc | ||
|
|
||
| # Diagnose registry connectivity and configuration | ||
| az acr check-health --name {registry} --yes | ||
| ``` | ||
|
|
||
| ## Key Principles | ||
|
|
||
| - **Prefer `az acr build` / ACR Tasks** over local `docker build` + `docker push`: builds run in Azure, work without a local daemon, and integrate with triggers. | ||
| - **Prefer `az acr import`** to move images between registries: it is server-side, faster, and requires no local storage. | ||
| - **Never enable the admin user for production** — use Microsoft Entra identities (RBAC roles `AcrPull`/`AcrPush`, or `Container Registry Repository Reader`/`Writer` on ABAC-enabled registries), repository-scoped tokens, or managed identities. | ||
| - **Premium-only features**: geo-replication, private endpoints, retention policies, connected registries, agent pools. (Repository-scoped tokens work in all tiers; zone redundancy is automatic in all tiers in supported regions.) | ||
|
|
||
| ## CLI Structure | ||
|
|
||
| ``` | ||
| az acr | ||
| ├── create / delete / list / show / update # Registry lifecycle | ||
| ├── login # Docker credential helper (or --expose-token) | ||
| ├── check-health / check-name / show-usage # Diagnostics & quota | ||
| ├── build # Cloud image build (quick task) | ||
| ├── run # Run a command / multi-step task once | ||
| ├── task # ACR Tasks (triggers, timers, logs, runs) | ||
| ├── agentpool # Dedicated task agent pools (Premium) | ||
| ├── import # Server-side image copy into the registry | ||
| ├── repository # List/show/delete/untag repos & tags, lock images | ||
| ├── manifest # Manifest metadata, delete, OCI referrers | ||
| ├── credential # Admin user credentials (avoid in production) | ||
| ├── token / scope-map # Repository-scoped tokens (Premium) | ||
| ├── replication # Geo-replication (Premium) | ||
| ├── network-rule # IP network rules | ||
| ├── private-endpoint-connection # Private Link approvals | ||
| ├── config # content-trust, retention, soft-delete, ... | ||
| ├── cache / credential-set # Artifact cache (pull-through cache) rules | ||
| ├── webhook # Push/delete event webhooks | ||
| ├── connected-registry # On-premises / IoT connected registries | ||
| └── export-pipeline / import-pipeline / pipeline-run # acrtransfer extension | ||
| ``` | ||
|
|
||
| ## Reference Files | ||
|
|
||
| Read the relevant reference file based on the user's task. Each file contains complete command syntax and examples for its domain. | ||
|
|
||
| | File | When to read | Covers | | ||
| |---|---|---| | ||
| | `references/auth-and-security.md` | Login failures, permissions, CI/CD or AKS pull access | `az acr login` (incl. `--expose-token`), Entra RBAC roles, service principals, managed identities, `--attach-acr` for AKS, repository-scoped tokens & scope maps, admin user, content trust | | ||
| | `references/build-and-tasks.md` | Building images in Azure, automation, CI triggers | `az acr build`, `az acr run`, multi-step task YAML, `az acr task` (git/base-image/timer triggers, logs, runs), agent pools | | ||
| | `references/images-and-artifacts.md` | Managing repos, tags, cleanup, storage costs | `az acr import`, repository & manifest commands, untag vs delete, purge (`acr purge`), image locking, retention policy, soft delete, artifact cache, `show-usage` | | ||
| | `references/networking-and-geo.md` | Multi-region, private access, edge scenarios | Geo-replication, zone redundancy, private endpoints, network rules, dedicated data endpoints, connected registries, registry transfer pipelines | |
174 changes: 174 additions & 0 deletions
174
skills/azure-container-registry-cli/references/auth-and-security.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| # Authentication & Security | ||
|
|
||
| ## Table of Contents | ||
| - [Individual Login](#individual-login) | ||
| - [Microsoft Entra RBAC Roles](#microsoft-entra-rbac-roles) | ||
| - [Service Principals](#service-principals) | ||
| - [Managed Identities](#managed-identities) | ||
| - [AKS Integration](#aks-integration) | ||
| - [Repository-Scoped Tokens](#repository-scoped-tokens) | ||
| - [Admin User](#admin-user) | ||
| - [Content Trust](#content-trust) | ||
|
|
||
| --- | ||
|
|
||
| ## Individual Login | ||
|
|
||
| ```bash | ||
| # Standard login — wires Docker/Podman credentials via your az login identity | ||
| az acr login --name {registry} | ||
|
|
||
| # Without a Docker daemon: get an Entra access token and pipe it to docker login | ||
| LOGIN_SERVER=$(az acr show --name {registry} --query loginServer --output tsv) | ||
| az acr login --name {registry} --expose-token --query accessToken --output tsv | \ | ||
| docker login $LOGIN_SERVER --username 00000000-0000-0000-0000-000000000000 --password-stdin | ||
| ``` | ||
|
|
||
| Notes: | ||
| - `az acr login` tokens are valid for 3 hours; re-run on expiry. | ||
| - Resolve the login server with `az acr show --name {registry} --query loginServer --output tsv` rather than hardcoding it: it is usually `{registry}.azurecr.io`, but sovereign clouds use other suffixes and registries with a domain name label scope get a hash suffix. | ||
|
|
||
| ## Microsoft Entra RBAC Roles | ||
|
|
||
| The applicable data-plane roles depend on the registry's **role assignment permissions mode** — check it first: | ||
|
|
||
| ```bash | ||
| az acr show --name {registry} --query roleAssignmentMode --output tsv | ||
| # LegacyRegistryPermissions -> use AcrPull/AcrPush/AcrDelete | ||
| # AbacRepositoryPermissions -> use Container Registry Repository Reader/Writer/Contributor | ||
| ``` | ||
|
|
||
| **Legacy mode (RBAC Registry Permissions):** | ||
|
|
||
| | Role | Permissions | | ||
| |---|---| | ||
| | `AcrPull` | Pull images | | ||
| | `AcrPush` | Pull + push images | | ||
| | `AcrDelete` | Delete images | | ||
| | `AcrImageSigner` | Sign images (content trust) | | ||
| | `Contributor`/`Owner` | Full control-plane management + push/pull | | ||
|
|
||
| **ABAC-enabled mode (RBAC Registry + ABAC Repository Permissions):** `AcrPull`/`AcrPush`/`AcrDelete` are **not honored**, and `Owner`/`Contributor`/`Reader` grant control-plane only. Use instead: | ||
|
|
||
| | Role | Permissions | | ||
| |---|---| | ||
| | `Container Registry Repository Reader` | Read images, tags, metadata (add ABAC conditions to scope to repositories) | | ||
| | `Container Registry Repository Writer` | Read + write/update | | ||
| | `Container Registry Repository Contributor` | Read + write + delete | | ||
| | `Container Registry Repository Catalog Lister` | List repositories — assign only when the identity must enumerate the catalog (e.g., `az acr repository list`); not needed for pull/push of known repositories | | ||
|
|
||
| ```bash | ||
| # Get the registry resource ID | ||
| ACR_ID=$(az acr show --name {registry} --query id --output tsv) | ||
|
|
||
| # Grant pull access to a user, group, service principal, or managed identity | ||
| az role assignment create --assignee {principal-id} --scope $ACR_ID --role AcrPull | ||
|
|
||
| # List who has access | ||
| az role assignment list --scope $ACR_ID --output table | ||
| ``` | ||
|
|
||
| ## Service Principals | ||
|
|
||
| For CI/CD systems that cannot use OIDC/managed identity: | ||
|
|
||
| ```bash | ||
| # Create an SP scoped to pull only | ||
| ACR_ID=$(az acr show --name {registry} --query id --output tsv) | ||
| az ad sp create-for-rbac --name {sp-name} --scopes $ACR_ID --role AcrPull | ||
|
|
||
| # Docker login with the SP — pipe the secret via stdin, never pass it as an argument | ||
| # (printf with a quoted variable preserves whitespace/glob characters exactly) | ||
| printf '%s' "$SP_PASSWORD" | docker login $LOGIN_SERVER --username {appId} --password-stdin | ||
| ``` | ||
|
|
||
| Prefer federated credentials (OIDC) over SP passwords in GitHub Actions / Azure DevOps when possible. | ||
|
|
||
| ## Managed Identities | ||
|
|
||
| For Azure compute (VM, App Service, Container Apps, Functions): | ||
|
|
||
| ```bash | ||
| # Assign a system-assigned identity and grant it pull | ||
| az vm identity assign --name {vm} --resource-group {rg} | ||
| PRINCIPAL_ID=$(az vm show --name {vm} --resource-group {rg} --query identity.principalId --output tsv) | ||
| az role assignment create --assignee $PRINCIPAL_ID --scope $ACR_ID --role AcrPull | ||
| ``` | ||
|
|
||
| App Service / Container Apps then pull with `--assign-identity` + `--acr-identity` style flags of their own CLIs — no registry password needed. | ||
|
|
||
| ## AKS Integration | ||
|
|
||
| ```bash | ||
| # Attach at cluster creation | ||
| az aks create --name {cluster} --resource-group {rg} --attach-acr {registry} | ||
|
|
||
| # Attach/detach an existing cluster (grants AcrPull to the kubelet identity) | ||
| az aks update --name {cluster} --resource-group {rg} --attach-acr {registry} | ||
|
AClerbois marked this conversation as resolved.
|
||
| az aks update --name {cluster} --resource-group {rg} --detach-acr {registry} | ||
|
|
||
| # Validate the cluster can reach the registry | ||
| az aks check-acr --name {cluster} --resource-group {rg} --acr {registry}.azurecr.io | ||
| ``` | ||
|
|
||
| `--attach-acr` requires Owner or User Access Administrator on the registry. Cross-subscription attach works by passing the full ACR resource ID. | ||
|
|
||
| ⚠️ `--attach-acr` assigns `AcrPull`, which is **not honored on ABAC-enabled registries** (`roleAssignmentMode` = `AbacRepositoryPermissions`). For those, assign the ABAC roles to the kubelet identity manually: | ||
|
|
||
| ```bash | ||
| ACR_ID=$(az acr show --name {registry} --query id --output tsv) | ||
| KUBELET_ID=$(az aks show --name {cluster} --resource-group {rg} \ | ||
| --query identityProfile.kubeletidentity.objectId --output tsv) | ||
| az role assignment create --assignee $KUBELET_ID --scope $ACR_ID \ | ||
| --role "Container Registry Repository Reader" | ||
| # "Container Registry Repository Catalog Lister" is NOT needed for pulls — | ||
| # only add it if the identity must list repositories | ||
| ``` | ||
|
|
||
| ## Repository-Scoped Tokens | ||
|
|
||
| Available in all service tiers. Fine-grained, non-Entra credentials (e.g., external partners, IoT devices): | ||
|
|
||
| ```bash | ||
| # 1. Create a scope map (actions: content/read, content/write, content/delete, metadata/read, metadata/write) | ||
| az acr scope-map create --name {scope-map} --registry {registry} \ | ||
| --repository app content/read metadata/read \ | ||
| --description "Pull-only access to app" | ||
|
|
||
| # 2. Create a token bound to the scope map | ||
| az acr token create --name {token} --registry {registry} --scope-map {scope-map} | ||
|
|
||
| # 3. Generate/rotate passwords (up to 2, optional expiry) | ||
| az acr token credential generate --name {token} --registry {registry} --password1 --expiration-in-days 30 | ||
|
|
||
| # Login with the token — pipe the password via stdin, never pass it as an argument | ||
| printf '%s' "$TOKEN_PWD" | docker login $LOGIN_SERVER --username {token} --password-stdin | ||
|
|
||
| # Disable or delete | ||
| az acr token update --name {token} --registry {registry} --status disabled | ||
| az acr token delete --name {token} --registry {registry} --yes | ||
| ``` | ||
|
|
||
| ## Admin User | ||
|
|
||
| Single account, full push/pull on the whole registry, not auditable per user — **keep disabled in production**: | ||
|
|
||
| ```bash | ||
| az acr update --name {registry} --admin-enabled false # recommended | ||
| az acr credential show --name {registry} # view username/passwords (if enabled) | ||
| az acr credential renew --name {registry} --password-name password2 # rotate | ||
| ``` | ||
|
|
||
| Legitimate uses: quick local tests, services that only accept username/password and cannot use tokens. | ||
|
|
||
| ## Content Trust (deprecated) | ||
|
|
||
| Docker Content Trust (DCT) is being retired: **since May 31, 2026 it cannot be enabled on new registries** (or on registries that never enabled it), and it will be removed entirely on March 31, 2028. Do not set up DCT — sign images with **Notation (Notary Project)** and store signatures as OCI artifacts instead; see "Transition from Docker Content Trust to Notary Project" in the ACR docs. | ||
|
|
||
| ```bash | ||
| # Registries with legacy DCT only — inspect or disable the existing configuration | ||
| az acr config content-trust show --registry {registry} | ||
| az acr config content-trust update --registry {registry} --status disabled | ||
| ``` | ||
|
|
||
| Legacy DCT signers needed `AcrImageSigner` in addition to `AcrPush`. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.