diff --git a/.codespellrc b/.codespellrc index d38ea35d8..7059de5b6 100644 --- a/.codespellrc +++ b/.codespellrc @@ -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 diff --git a/docs/README.skills.md b/docs/README.skills.md index 46d2bb38b..fafe77964 100644 --- a/docs/README.skills.md +++ b/docs/README.skills.md @@ -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)
`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)
`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)
`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.
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`
`assets/06-architecture-diagram.png`
`assets/07-azure-portal-resources.png`
`assets/08-deployment-succeeded.png`
`references/ai-data.md`
`references/architecture-guidance-sources.md`
`references/azure-common-patterns.md`
`references/azure-dynamic-sources.md`
`references/bicep-generator.md`
`references/bicep-reviewer.md`
`references/phase0-scanner.md`
`references/phase1-advisor.md`
`references/phase4-deployer.md`
`references/service-gotchas.md`
`scripts/cli.py`
`scripts/generator.py`
`scripts/icons.py` | +| [azure-container-registry-cli](../skills/azure-container-registry-cli/SKILL.md)
`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`
`references/build-and-tasks.md`
`references/images-and-artifacts.md`
`references/networking-and-geo.md` | | [azure-deployment-preflight](../skills/azure-deployment-preflight/SKILL.md)
`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`
`references/REPORT-TEMPLATE.md`
`references/VALIDATION-COMMANDS.md` | | [azure-devops-cli](../skills/azure-devops-cli/SKILL.md)
`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`
`references/boards-and-iterations.md`
`references/long-comments-on-windows.md`
`references/org-and-security.md`
`references/pipelines-and-builds.md`
`references/repos-and-prs.md`
`references/variables-and-agents.md`
`references/workflows-and-patterns.md` | | [azure-pricing](../skills/azure-pricing/SKILL.md)
`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`
`references/COST-ESTIMATOR.md`
`references/REGIONS.md`
`references/SERVICE-NAMES.md` | diff --git a/skills/azure-container-registry-cli/SKILL.md b/skills/azure-container-registry-cli/SKILL.md new file mode 100644 index 000000000..615430329 --- /dev/null +++ b/skills/azure-container-registry-cli/SKILL.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 | diff --git a/skills/azure-container-registry-cli/references/auth-and-security.md b/skills/azure-container-registry-cli/references/auth-and-security.md new file mode 100644 index 000000000..4c9985c3e --- /dev/null +++ b/skills/azure-container-registry-cli/references/auth-and-security.md @@ -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`. diff --git a/skills/azure-container-registry-cli/references/build-and-tasks.md b/skills/azure-container-registry-cli/references/build-and-tasks.md new file mode 100644 index 000000000..84430cce4 --- /dev/null +++ b/skills/azure-container-registry-cli/references/build-and-tasks.md @@ -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 ... +``` diff --git a/skills/azure-container-registry-cli/references/images-and-artifacts.md b/skills/azure-container-registry-cli/references/images-and-artifacts.md new file mode 100644 index 000000000..554e7457b --- /dev/null +++ b/skills/azure-container-registry-cli/references/images-and-artifacts.md @@ -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. diff --git a/skills/azure-container-registry-cli/references/networking-and-geo.md b/skills/azure-container-registry-cli/references/networking-and-geo.md new file mode 100644 index 000000000..86595dacd --- /dev/null +++ b/skills/azure-container-registry-cli/references/networking-and-geo.md @@ -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`).