chore: publish from main

This commit is contained in:
github-actions[bot]
2026-07-30 01:53:16 +00:00
parent cf3c70d8d2
commit 8df98cb45e
7 changed files with 732 additions and 1 deletions
+3 -1
View File
@@ -62,7 +62,9 @@
# Vally/vally - Name of product
ignore-words-list = numer,wit,aks,edn,ser,ois,gir,rouge,categor,aline,ative,afterall,deques,dateA,dateB,TE,FillIn,alle,vai,LOD,InOut,pixelX,aNULL,Wee,Sherif,queston,extenions,Vertexes,nin,FO,CAF,Parth,ans,gud,Vally,vally
# ACI - Azure Container Instances abbreviation
ignore-words-list = numer,wit,aks,edn,ser,ois,gir,rouge,categor,aline,ative,afterall,deques,dateA,dateB,TE,FillIn,alle,vai,LOD,InOut,pixelX,aNULL,Wee,Sherif,queston,extenions,Vertexes,nin,FO,CAF,Parth,ans,gud,Vally,vally,ACI
# Skip certain files and directories
# *.tm7 - MTM DataContract exports; embedded base64 icon blobs trigger false positives
+1
View File
@@ -70,6 +70,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to
| [aws-well-architected-review](../skills/aws-well-architected-review/SKILL.md)<br />`gh skills install github/awesome-copilot aws-well-architected-review` | Perform an AWS Well-Architected Framework review of the current workload IaC and architecture, generating findings and GitHub issues for improvements. | None |
| [az-cost-optimize](../skills/az-cost-optimize/SKILL.md)<br />`gh skills install github/awesome-copilot az-cost-optimize` | Analyze Azure resources used in the app (IaC files and/or resources in a target rg) and optimize costs - creating GitHub issues for identified optimizations. | None |
| [azure-architecture-autopilot](../skills/azure-architecture-autopilot/SKILL.md)<br />`gh skills install github/awesome-copilot azure-architecture-autopilot` | Design Azure infrastructure using natural language, or analyze existing Azure resources to auto-generate architecture diagrams, refine them through conversation, and deploy with Bicep.<br />When to use this skill: - "Create X on Azure", "Set up a RAG architecture" (new design) - "Analyze my current Azure infrastructure", "Draw a diagram for rg-xxx" (existing analysis) - "Foundry is slow", "I want to reduce costs", "Strengthen security" (natural language modification) - Azure resource deployment, Bicep template generation, IaC code generation - Microsoft Foundry, AI Search, OpenAI, Fabric, ADLS Gen2, Databricks, and all Azure services | `.gitignore`<br />`assets/06-architecture-diagram.png`<br />`assets/07-azure-portal-resources.png`<br />`assets/08-deployment-succeeded.png`<br />`references/ai-data.md`<br />`references/architecture-guidance-sources.md`<br />`references/azure-common-patterns.md`<br />`references/azure-dynamic-sources.md`<br />`references/bicep-generator.md`<br />`references/bicep-reviewer.md`<br />`references/phase0-scanner.md`<br />`references/phase1-advisor.md`<br />`references/phase4-deployer.md`<br />`references/service-gotchas.md`<br />`scripts/cli.py`<br />`scripts/generator.py`<br />`scripts/icons.py` |
| [azure-container-registry-cli](../skills/azure-container-registry-cli/SKILL.md)<br />`gh skills install github/awesome-copilot azure-container-registry-cli` | 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. | `references/auth-and-security.md`<br />`references/build-and-tasks.md`<br />`references/images-and-artifacts.md`<br />`references/networking-and-geo.md` |
| [azure-deployment-preflight](../skills/azure-deployment-preflight/SKILL.md)<br />`gh skills install github/awesome-copilot azure-deployment-preflight` | Performs comprehensive preflight validation of Bicep deployments to Azure, including template syntax validation, what-if analysis, and permission checks. Use this skill before any deployment to Azure to preview changes, identify potential issues, and ensure the deployment will succeed. Activate when users mention deploying to Azure, validating Bicep files, checking deployment permissions, previewing infrastructure changes, running what-if, or preparing for azd provision. | `references/ERROR-HANDLING.md`<br />`references/REPORT-TEMPLATE.md`<br />`references/VALIDATION-COMMANDS.md` |
| [azure-devops-cli](../skills/azure-devops-cli/SKILL.md)<br />`gh skills install github/awesome-copilot azure-devops-cli` | Manage Azure DevOps resources via CLI including projects, repos, pipelines, builds, pull requests, work items, artifacts, and service endpoints. Use when working with Azure DevOps, az commands, devops automation, CI/CD, or when user mentions Azure DevOps CLI. | `references/advanced-usage.md`<br />`references/boards-and-iterations.md`<br />`references/long-comments-on-windows.md`<br />`references/org-and-security.md`<br />`references/pipelines-and-builds.md`<br />`references/repos-and-prs.md`<br />`references/variables-and-agents.md`<br />`references/workflows-and-patterns.md` |
| [azure-pricing](../skills/azure-pricing/SKILL.md)<br />`gh skills install github/awesome-copilot azure-pricing` | Fetches real-time Azure retail pricing using the Azure Retail Prices API (prices.azure.com) and estimates Copilot Studio agent credit consumption. Use when the user asks about the cost of any Azure service, wants to compare SKU prices, needs pricing data for a cost estimate, mentions Azure pricing, Azure costs, Azure billing, or asks about Copilot Studio pricing, Copilot Credits, or agent usage estimation. Covers compute, storage, networking, databases, AI, Copilot Studio, and all other Azure service families. | `references/COPILOT-STUDIO-RATES.md`<br />`references/COST-ESTIMATOR.md`<br />`references/REGIONS.md`<br />`references/SERVICE-NAMES.md` |
@@ -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 |
@@ -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}
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`.
@@ -0,0 +1,147 @@
# Builds & ACR Tasks
## Table of Contents
- [Quick Build (az acr build)](#quick-build-az-acr-build)
- [Run a Command or Multi-Step Task Once (az acr run)](#run-a-command-or-multi-step-task-once-az-acr-run)
- [ACR Tasks (az acr task)](#acr-tasks-az-acr-task)
- [Triggers](#triggers)
- [Multi-Step Task YAML](#multi-step-task-yaml)
- [Agent Pools](#agent-pools)
---
## Quick Build (az acr build)
Builds in Azure and pushes to the registry — no local Docker daemon required:
```bash
# Build from the current directory and push
az acr build --registry {registry} --image app:v1 .
# Custom Dockerfile, build args, target platform
az acr build --registry {registry} --image app:v1 \
--file docker/Dockerfile.prod \
--build-arg VERSION=1.2.3 \
--platform linux/amd64 .
# Cross-platform: each build produces ONE single-architecture image for the target platform
az acr build --registry {registry} --image app:v1-arm64 --platform linux/arm64 .
# For a true multi-arch image, build once per platform under arch-specific tags, then
# assemble and push a manifest list (docker manifest create/push, or docker buildx locally)
# Build directly from a Git repo (no local clone)
az acr build --registry {registry} --image app:v1 https://github.com/{org}/{repo}.git#{branch}:{folder}
# Build without pushing (validation only)
az acr build --registry {registry} --image app:test --no-push .
```
Notes:
- The build context is uploaded; use a `.dockerignore` to keep it small.
- Tag with a unique value per build (git SHA, run ID) — avoid relying on `latest`.
## Run a Command or Multi-Step Task Once (az acr run)
```bash
# Run a container command in the registry's task runner (context /dev/null = no upload)
az acr run --registry {registry} --cmd '{registry}.azurecr.io/app:v1' /dev/null
# Execute a multi-step task file against the current directory
az acr run --registry {registry} --file acb.yaml .
```
## ACR Tasks (az acr task)
Persistent, triggerable build definitions:
```bash
# Create a task that builds on every commit to main
az acr task create --registry {registry} --name build-app \
--image "app:{{.Run.ID}}" \
--context https://github.com/{org}/{repo}.git#main \
--file Dockerfile \
--git-access-token {pat} \
--commit-trigger-enabled true \
--base-image-trigger-enabled true
# Manually trigger, list, inspect
az acr task run --registry {registry} --name build-app
az acr task list --registry {registry} --output table
az acr task list-runs --registry {registry} --name build-app --output table
az acr task logs --registry {registry} --name build-app # latest run
az acr task logs --registry {registry} --run-id {run-id}
# Update / disable / delete
az acr task update --registry {registry} --name build-app --image "app:{{.Run.ID}}"
az acr task update --registry {registry} --name build-app --status Disabled
az acr task delete --registry {registry} --name build-app --yes
```
Useful run variables for `--image`: `{{.Run.ID}}`, `{{.Run.Commit}}`, `{{.Run.Branch}}`, `{{.Run.Date}}`.
⚠️ On **ABAC-enabled registries** (`roleAssignmentMode` = `AbacRepositoryPermissions`), tasks and quick builds/runs have no default access to the source registry. Pass `--source-acr-auth-id [caller]` to `az acr build`/`az acr run`, and `--source-acr-auth-id [system]` (or a user-assigned identity resource ID) to `az acr task create`/`update`, then grant that identity the `Container Registry Repository ...` roles. Ensure the task actually has that identity — add `--assign-identity [system]` at creation, or run `az acr task identity assign` on an existing task, before referencing it.
## Triggers
```bash
# Timer trigger (cron in UTC) — e.g., nightly rebuild
az acr task timer add --registry {registry} --name build-app \
--timer-name nightly --schedule "0 2 * * *"
az acr task timer list --registry {registry} --name build-app
az acr task timer remove --registry {registry} --name build-app --timer-name nightly
```
- **Commit trigger**: rebuild on push to the tracked branch (`--commit-trigger-enabled`).
- **Base image trigger**: rebuild automatically when the base image (e.g., a patched `mcr.microsoft.com` image) is updated (`--base-image-trigger-enabled`) — key for OS/framework patching.
- **Timer trigger**: cron schedules; also the standard way to schedule `acr purge` cleanup (see `images-and-artifacts.md`).
Tasks that access other registries or Azure resources can use an identity:
```bash
az acr task identity assign --registry {registry} --name build-app # system-assigned
az acr task credential add --registry {registry} --name build-app \
--login-server {other-registry}.azurecr.io --use-identity [system]
```
## Multi-Step Task YAML
`acb.yaml` — build, test, then push only on success:
```yaml
version: v1.1.0
steps:
- build: -t $Registry/app:{{.Run.ID}} -f Dockerfile .
- cmd: $Registry/app:{{.Run.ID}} run-tests
- push:
- $Registry/app:{{.Run.ID}}
```
```bash
# Run once
az acr run --registry {registry} --file acb.yaml .
# Or create a triggered task from the YAML
az acr task create --registry {registry} --name build-test-push \
--file acb.yaml \
--context https://github.com/{org}/{repo}.git#main \
--git-access-token {pat}
```
## Agent Pools
Premium SKU. Dedicated task compute — for more CPU, or one of the two supported ways to run tasks against a network-restricted registry (the other being trusted services + the task network bypass policy, see `networking-and-geo.md`):
```bash
az acr agentpool create --registry {registry} --name pool1 --tier S2 # S1/S2/S3/I6
# For the firewall/VNet scenario, the pool MUST be attached to a subnet that can
# reach the registry's private endpoint — without --subnet-id it runs outside the VNet
az acr agentpool create --registry {registry} --name pool1 --tier S2 \
--subnet-id /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vnet}/subnets/{subnet}
az acr agentpool list --registry {registry} --output table
# Target the pool
az acr build --registry {registry} --agent-pool pool1 --image app:v1 .
az acr task create --registry {registry} --name build-app --agent-pool pool1 ...
```
@@ -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.
@@ -0,0 +1,147 @@
# Networking & Geo-Replication
## Table of Contents
- [Geo-Replication](#geo-replication)
- [Zone Redundancy](#zone-redundancy)
- [Private Endpoints (Private Link)](#private-endpoints-private-link)
- [Public Network Rules](#public-network-rules)
- [Dedicated Data Endpoints](#dedicated-data-endpoints)
- [Connected Registry](#connected-registry)
- [Registry Transfer Pipelines](#registry-transfer-pipelines)
Geo-replication, private endpoints, public IP network rules, dedicated data endpoints, connected registries, and transfer pipelines require the **Premium** SKU. Zone redundancy is automatic in every tier.
---
## Geo-Replication
One registry, one login server, images served from the nearest region:
```bash
az acr replication create --registry {registry} --location westeurope
az acr replication list --registry {registry} --output table
az acr replication show --registry {registry} --name westeurope
az acr replication delete --registry {registry} --name westeurope
# Regional endpoint status (useful for webhook/replication debugging)
az acr replication update --registry {registry} --name westeurope --region-endpoint-enabled true
```
Pushes replicate automatically; clients keep pulling `{registry}.azurecr.io` and Traffic Manager routes to the closest replica.
## Zone Redundancy
Zone redundancy is **enabled automatically for all registries, in all tiers (Basic/Standard/Premium), in regions that support availability zones** — no flag, SKU, or action required, and it cannot be disabled. Geo-replicas in supported regions are also zone-redundant by default.
Do not rely on the `zoneRedundancy` property or the legacy `--zone-redundancy` flag: the property is a deprecated artifact that may display `Disabled` even though the registry is fully zone-redundant. Registries in regions without availability-zone support are the only exception — migrate them (via `az acr import` or a transfer pipeline) to a supported region.
## Private Endpoints (Private Link)
```bash
# 1. Disable network policies on the endpoint subnet if needed, then create the endpoint
az network private-endpoint create --resource-group {rg} --name {registry}-pe \
--vnet-name {vnet} --subnet {subnet} \
--private-connection-resource-id $(az acr show --name {registry} --query id --output tsv) \
--group-ids registry \
--connection-name {registry}-pe-conn
# 2. Private DNS so {registry}.azurecr.io resolves to the private IP
az network private-dns zone create --resource-group {rg} --name privatelink.azurecr.io
az network private-dns link vnet create --resource-group {rg} \
--zone-name privatelink.azurecr.io --name {registry}-dns-link --virtual-network {vnet} --registration-enabled false
az network private-endpoint dns-zone-group create --resource-group {rg} \
--endpoint-name {registry}-pe --name default \
--private-dns-zone privatelink.azurecr.io --zone-name registry
# 3. Optionally shut off public access entirely
az acr update --name {registry} --public-network-enabled false
# Manage connection approvals
az acr private-endpoint-connection list --registry-name {registry} --output table
az acr private-endpoint-connection approve --registry-name {registry} --name {connection}
```
Notes:
- Each private endpoint creates records for the registry **and** its data endpoint(s) (`{registry}.{region}.data.azurecr.io`) — geo-replicated registries need one data record per region.
- With public access disabled, standard ACR Tasks agents cannot reach the registry — use a dedicated agent pool attached to a subnet in the VNet, or enable trusted services **and** the task network bypass policy (see below).
## Public Network Rules
Restrict public access to specific IPs instead of (or before) going fully private:
```bash
# Default-deny, then allow specific ranges
az acr update --name {registry} --default-action Deny
az acr network-rule add --name {registry} --ip-address 203.0.113.0/24
az acr network-rule list --name {registry}
az acr network-rule remove --name {registry} --ip-address 203.0.113.0/24
# Let trusted Azure services (e.g., Defender, ACI, image import) through the firewall
az acr update --name {registry} --allow-trusted-services true
```
⚠️ **Since June 1, 2025, `--allow-trusted-services` alone is NOT enough for ACR Tasks using a system-assigned managed identity** — without the task network bypass policy, their runs get 403 errors on a network-restricted registry. Enable it explicitly:
```bash
az resource update \
--namespace Microsoft.ContainerRegistry --resource-type registries \
--name {registry} --resource-group {rg} \
--api-version 2025-06-01-preview \
--set properties.networkRuleBypassAllowedForTasks=true
```
Alternatives that avoid the bypass entirely: run tasks in a VNet-attached agent pool, or run `acr purge` locally with the [acr-cli binary](https://github.com/azure/acr-cli). Tasks using a user-assigned identity are not affected.
## Dedicated Data Endpoints
Give layer downloads stable, registry-specific FQDNs (`{registry}.{region}.data.azurecr.io`) instead of shared storage endpoints — simplifies client-side firewall rules:
```bash
az acr update --name {registry} --data-endpoint-enabled true
az acr show-endpoints --name {registry}
```
## Connected Registry
On-premises / IoT edge mirror of a cloud registry:
```bash
# Parent registry must have a dedicated data endpoint
az acr update --name {registry} --data-endpoint-enabled true
az acr connected-registry create --registry {registry} --name {connected-name} \
--repository "app" "hello-world" \
--mode ReadOnly # or ReadWrite
az acr connected-registry list --registry {registry} --output table
az acr connected-registry get-settings --registry {registry} --name {connected-name} \
--parent-protocol https --generate-password 1
az acr connected-registry deactivate --registry {registry} --name {connected-name}
```
## Registry Transfer Pipelines
Move images between disconnected clouds/tenants via storage blobs (extension `acrtransfer`):
```bash
az extension add --name acrtransfer
# Export from source registry to a storage container (SAS token in Key Vault)
az acr export-pipeline create --resource-group {rg} --registry {src-registry} \
--name export-pipe \
--secret-uri https://{vault}.vault.azure.net/secrets/{sas-secret} \
--storage-container-uri https://{account}.blob.core.windows.net/{container}
# Import on the target side
az acr import-pipeline create --resource-group {rg} --registry {dst-registry} \
--name import-pipe \
--secret-uri https://{vault}.vault.azure.net/secrets/{sas-secret} \
--storage-container-uri https://{account}.blob.core.windows.net/{container}
# Run an export
az acr pipeline-run create --resource-group {rg} --registry {src-registry} \
--pipeline export-pipe --name run1 --pipeline-type export \
--artifacts app:v1 app:v2 --storage-blob transfer-blob-1
```
For simple same-cloud copies prefer `az acr import` (see `images-and-artifacts.md`).