Manage container images in Azure Container Registry
How a registry stores an image
Run docker push myregistry.azurecr.io/myrepo:v1 twice, with different code each time, and the registry now holds two images while the v1 tag names only the second. Nothing was overwritten and nothing was lost: the tag moved. Manifests are content and never change, tags are labels and move freely, and that split is the root of almost every surprise in this objective. It is worth pinning down the five things a registry actually keeps.
This page owns an image once it exists: how you name it, pin it, copy it between registries, and eventually remove it. The ACR Tasks page owns how the image gets built and pushed in the first place, including cloud builds and the triggers that rebuild on a source commit or a base-image update.
Two words here collide with words you already use elsewhere: a repository is a registry repository, a named collection of image versions, not a Git repository, and a tag is an image tag, not an Azure resource tag.
Microsoft's registry concepts[1] article names the parts, and this page uses those names throughout:
- A registry stores and distributes container images and related artifacts. In Azure it is a resource with a login server name in the form
myregistry.azurecr.io, always lowercase. - A repository is a collection of artifacts in one registry that share a name but have different tags, such as
acr-helloworld:latest,acr-helloworld:v1, andacr-helloworld:v2. Forward slashes create namespaces (marketing/campaign10-18/web:v2), but the registry manages every repository independently rather than as a hierarchy. - A tag specifies an artifact's version. One artifact can carry one tag, several, or none: you can assign many tags to a single artifact within a repository, and you can untag an artifact by deleting all of its tags while the image's data stays in the registry.
- Layers are the pieces an image is assembled from; in a Docker container image each layer corresponds to a line in the Dockerfile that defines the image. Artifacts within one registry share common layers, so a base layer used by ten images is stored once, which is the same layer reuse[2] Docker relies on locally. Separate registries never share layers with each other, which is deliberate isolation rather than an oversight.
- A manifest is the record the registry generates when you push. It uniquely identifies the artifact and lists its layers, and it carries a SHA-256 hash of its own called the manifest digest.
The digest is what lets you name an image without ambiguity. Every artifact in the registry, tagged or untagged, has its own digest, and that value is unique even when the artifact's layer data exactly matches another's. That is precisely why you can push myimage:latest over and over without an error: each push produces a new manifest with a new digest, and the tag simply stops pointing at the previous one.
An artifact therefore has two address forms, and telling them apart is worth a question on its own.
Two ways to address the same artifact
# By tag: resolves to whatever the tag points at right now.
myregistry.azurecr.io/acr-helloworld:v2
# By digest: resolves to exactly one manifest, permanently.
myregistry.azurecr.io/acr-helloworld@sha256:0a2e01852872...
The digest above is truncated with ... for readability; a real manifest digest is 64 hexadecimal characters. Both forms work with docker pull and with every Azure service that pulls from a registry.
The figure below assembles the five parts into one picture. Read it downward: the registry holds repositories, each repository holds tags and manifests, arrows run from a tag to the manifest it currently names, and every manifest resolves to layers the registry stores once and shares. Notice that v2 and latest both point at the same manifest, which is what one artifact carrying several tags looks like in practice.
The digest, then, is the only name on this page guaranteed to mean the same thing tomorrow.
Choosing a tagging strategy
Microsoft's tagging guidance offers exactly two approaches, and they optimise for opposite things: use stable tags to maintain base images, and unique tags for deployments[3]. Pick the wrong one and the failure is not an error message; it is two nodes in the same deployment quietly running different code.
Stable tags
A stable tag is a tag you reuse. Stable does not mean the contents are frozen; it means the image stays stable for the intent of that version, so it can still be serviced with security patches or framework updates. A framework team shipping version 1.0 typically keeps two of them: :1, which always resolves to the newest 1.x release, and :1.0, which follows updates to 1.0 without ever rolling forward to 1.1. When a base-image update or a servicing release lands, the team re-points those tags at the newest digest.
The recommendation is narrow and worth quoting in your head at exam time: use stable tags to maintain base images, and avoid deployments with stable tags, because those tags continue to receive updates and can introduce inconsistencies in production.
Unique tags
A unique tag is a tag that is never reused: every image pushed carries a tag no other image has. Microsoft names four schemes and is unusually candid about what each one costs you:
| Scheme | Example | The catch |
|---|---|---|
| Date-time stamp | 20260727-1830 | You can see when it was built, but correlating it back to a specific build run, across time zones, is awkward. |
| Git commit | a1b2c3d | Only semi-stable: a base-image update rebuilds the same commit with new content, so one commit can name two different images. |
| Manifest digest | sha256:0a2e... | Genuinely unique, but long, unreadable, and uncorrelated with your build environment. |
| Build ID | 1041 | Usually the best option: incremental, and it leads you straight back to the build's artifacts and logs. |
Where several build systems coexist, prefixing with the system name (<build-system>-<build-id>, for example jenkins-1041 beside pipelines-1041) keeps their numbering apart.
The reason deployments want the unique variant is scale-out consistency. If your container restarts, or an orchestrator scales out more instances, a unique tag guarantees the new host pulls the same image the existing instances are running. A stable tag makes no such promise, because it is designed to move.
latest is a default, not a version
latest invites a specific misreading, so deal with it head on: it is simply the tag Docker and the registry assume when you do not name one. Nothing in the registry keeps it pointing at your newest build. Push myimage:v3 and latest does not budge; it moves only when a push actually carries the latest tag, which is what happens when you omit the tag entirely. And because latest is reused by definition, it is a stable tag in Microsoft's sense, which puts it squarely inside the guidance to avoid deploying from stable tags.
The figure below shows the two strategies running side by side over three builds of the same component. Each unique tag is created once and stays pinned to its own manifest, while the single stable tag 1.0 is re-pointed as each serviced build arrives, which is exactly the behaviour a base-image consumer wants and a deployment does not.
Two consequences follow, and each has its own section on this page. A tag you deploy should be locked so nothing can move or delete it, covered next. And every re-point of a stable tag leaves the previous manifest behind without a tag, which is where registry storage quietly grows; that is the subject of What happens to a manifest after its last tag below.
Lock a tag, a manifest, or a repository
A tagged image in Azure Container Registry is mutable by default, so with push permission anyone can update and push an image with the same tag as often as they like. When you deploy to production you usually want the opposite, and image locking[4] is the mechanism that gets you there. Microsoft recommends locking any deployed image tag by setting its write-enabled attribute to false, and folding that step into the release pipeline.
Locking is an attribute change, not a separate feature: one command, az acr repository update, sets four changeable attributes at whichever scope you target.
| Attribute | Set to false to | Effect on other operations |
|---|---|---|
write-enabled | Block overwrite and deletion | The strongest lock; use it on a deployed tag |
delete-enabled | Block deletion only | Updates are still allowed |
read-enabled | Block read (pull) operations | The artifact stays present but cannot be pulled |
list-enabled | Keep the artifact out of listing operations | Does not affect pull or delete |
The scope comes from which parameter you pass, and all three take the same attribute flags.
Locking at three scopes
# One tag: myrepo:tag can no longer be overwritten or deleted.
az acr repository update --name myregistry \
--image myrepo:tag --write-enabled false
# One manifest, addressed by digest.
az acr repository update --name myregistry \
--image myrepo@sha256:123456abcdefg --write-enabled false
# The whole repository, and every image in it.
az acr repository update --name myregistry \
--repository myrepo --write-enabled false
# Protect from deletion but still allow updates.
az acr repository update --name myregistry \
--image myrepo:tag --delete-enabled false --write-enabled true
Unlocking is the same command with the attributes set back to true.
One detail catches people out often enough that Microsoft calls it out in a note: the changeable attributes of a tag and of its manifest are managed separately. Setting deleteEnabled=false on the tag does not set it on the corresponding manifest, so after unlocking a tag you may still need a second az acr repository update against myrepo@sha256:... to release the manifest. The --image parameter accepts either form, which is what makes the two-step dance easy to miss.
A name collision is worth clearing up here too, because the two things sound identical and protect completely different resources. Repository-level locking, the subject of this section, is set with az acr repository update and governs the data in your registry. Azure resource locks, set in the portal under Settings > Locks or with az lock, govern management operations on the registry resource itself, such as adding a replication or deleting the registry. A resource lock does not stop anyone from creating, updating, or deleting data in your repositories.
Locks also change what the cleanup mechanisms in the next-but-one section are allowed to touch, and that is intentional: a locked production image survives an aggressive purge. The takeaway is that locking gives you immutability by policy while a digest gives you immutability by naming, and each covers exactly what the other cannot: a digest does nothing to stop someone deleting the image, and a lock does nothing to stop a deployment following a tag that moved. Production usually wants both.
Copy images with az acr import
Copying an image between registries with Docker means a round trip through your machine: docker pull the source, docker tag it, docker push it to the target. Every layer travels down to your workstation and back up again. az acr import[5] replaces all three commands with a single Azure API call that copies the artifact registry to registry, and the image data never touches your machine.
That difference buys three things worth knowing by name. Your client environment does not need a local Docker installation, so you can import any container image regardless of its OS type. If you import a multi-architecture image, images for all architectures and platforms specified in its manifest list, the index that names one manifest per architecture, are copied in one operation. And if you have access to the target registry, you do not need the registry's public endpoint.
The figure below contrasts the two data paths.
Naming the source
You are pointing --source at something specific: a public image, your own dev registry, a partner's registry in another tenant, or a private registry of your own. Which of those it is decides both the string you write and the credentials you supply. Four cases cover the documented scenarios:
| Source | What --source takes | Credentials |
|---|---|---|
| Public registry | Full path, such as docker.io/library/hello-world:latest or mcr.microsoft.com/windows/servercore:ltsc2022 | None. For Docker Hub you may pass an account with --username and --password |
| Another registry in the same Microsoft Entra tenant | Repository and tag only, with --registry <source-registry-resource-id> | Your Microsoft Entra identity |
| A registry in a different tenant | Full login server path, sourceregistry.azurecr.io/sourcerepo:tag | A service principal app ID and password, a repository-scoped token, or an access token passed as --password |
| A non-Azure private registry | Full host path | --username and --password for that registry |
The second row is the one people get wrong: naming a source Azure registry by its resource ID rather than its login server is what switches authentication to Microsoft Entra, and it is also the only form that works when the source registry has public network access disabled. Cross-subscription imports in the same tenant use exactly the same --registry form.
That table also disposes of a common assumption. az acr import is not limited to publicly reachable images: private non-Azure registries, network-restricted Azure registries, and registries in other tenants are all supported, each with its own credential form.
Importing by tag and by digest
# By tag, from Docker Hub, into the target repository hello-world.
az acr import --name myregistry \
--source docker.io/library/hello-world:latest \
--image hello-world:latest
# By digest, with no tag applied in the target: --repository, not --image.
az acr import --name myregistry \
--source docker.io/library/hello-world@sha256:abc123 \
--repository hello-world
# From another registry in the same tenant, by resource ID.
az acr import --name myregistry \
--source aci-helloworld:latest --image aci-helloworld:latest \
--registry /subscriptions/.../providers/Microsoft.ContainerRegistry/registries/mysourceregistry
The resource ID in the last example is abbreviated with ...; a real one carries the full subscription and resource-group path. Note the parameter swap in the middle command: importing by digest without adding a tag uses --repository to name the destination repository, where a tagged import uses --image to name the destination repository and tag together. Identifying an image by its manifest digest instead of by tag guarantees a particular version of the image, which is the point of the exercise when you are pinning someone else's base image.
What can stop an import
Four constraints account for most import failures, and they are all documented rather than mysterious:
- Permissions. Your identity needs the
Container Registry Data Importer and Data Readerrole on the target registry to trigger imports, and the same role on the source registry when you are importing from another Azure registry in the same tenant. - Network restrictions. A registry with a private endpoint or firewall rules, on either end, must allow access by trusted services for import to bypass the network. That setting is enabled by default, so imports work unless someone turned it off. Cross-tenant import is not supported at all against a registry with public access disabled.
- Source-server behaviour. Import requires the external registry to support RFC 7233 range requests, the HTTP mechanism for fetching a byte range of a blob. A source that does not returns errors such as The remote server may not be RFC 7233 compliant.
- Size of the manifest list. The maximum number of manifests for an imported image is 50, which only bites on very broad multi-architecture images.
The habit to build: reach for az acr import whenever an image needs to move between registries, name the source by digest when the exact build matters, and let the credential form follow from where the source lives.
What happens to a manifest after its last tag
Untagging an image frees no space at all. Deleting a tag with az acr repository untag, or pushing a new image over an existing tag, removes only the tag reference: the manifest and its layer data remain in the registry[6]. What you are left with is an untagged manifest, also called an orphaned or dangling image, and it keeps consuming your storage quota while being invisible to any listing that goes by tag.
This is not a rare edge case. Every re-point of a stable tag produces one, by design, and a busy build pipeline can produce hundreds. Microsoft's own tagging guidance pairs the stable-tag recommendation with the instruction to periodically delete the untagged manifests those updates leave behind.
What deleting actually reclaims
Deleting a manifest by digest removes that manifest, every tag pointing at it, and the layers unique to it. Layers shared with other images in the registry are not deleted, because they are still referenced. That is the same layer-sharing behaviour from the first section seen from the other side: sharing saves you space on push and limits what you get back on delete. Billing for deleted data stops immediately, but the registry reclaims the space with an asynchronous process, so storage usage in az acr show-usage catches up a little later.
The figure below traces the whole path, from the moment a manifest loses its last tag through the three removal routes to the two possible endings.
The three removal routes
The comparison table in this page's overview sets them side by side; what follows is how each one behaves in practice.
Delete by digest is the manual route. List the manifests, pick a digest, and delete it. Because a digest can carry several tags, the delete takes all of them with it, which the CLI prompts you to confirm.
Deleting one manifest by digest
# List digests and their tags, then delete one of them.
az acr manifest list-metadata --name acr-helloworld --registry myregistry
az acr repository delete --name myregistry \
--image acr-helloworld@sha256:3168a21b98836dda...
The digest above is truncated with .... Deleting an entire repository (az acr repository delete --repository myrepo) is the wholesale version of the same operation.
acr purge[7] is the automated route, and it is currently in preview. It is a container command designed to run inside an ACR task, distributed as a public image and invoked through the acr purge alias, so it authenticates to the registry where the task runs without any credential handling on your part. Run it on demand with az acr run, or create a scheduled task with a cron expression. Its behaviour is governed by a handful of parameters:
--filtertakes a repository name regular expression and a tag name regular expression, for example--filter 'hello-world:.*'. You can pass several.--agotakes a Go-style duration such as2d3h6mor1.5h, and selects images last modified more than that long ago. It and--filterare the two you must supply.--untaggedadditionally deletes manifests that have no tags. Without it,acr purgedeletes only tag references and leaves the manifests behind, which is the single most common misunderstanding of the command.--untagged-onlydeletes only untagged manifests and skips tag deletion entirely, which makes--filterand--agooptional.--dry-runproduces the same output while deleting nothing, and--keep Nretains the N most recently modified matching tags per repository.
Previewing a purge, then scheduling it
# Dry-run first, then schedule the real thing daily at 00:00 UTC.
PURGE_CMD="acr purge --filter 'hello-world:.*' --ago 7d --untagged --dry-run"
az acr run --cmd "$PURGE_CMD" --registry myregistry /dev/null
az acr task create --name purgeTask \
--cmd "acr purge --filter 'hello-world:.*' --ago 7d --untagged" \
--schedule "0 0 * * *" --registry myregistry --context /dev/null
Purging thousands of artifacts can exceed the default task timeout of 600 seconds on demand or 3,600 seconds when scheduled, in which case only a subset is deleted; --timeout raises the ceiling. And acr purge will not delete a tag or repository whose write-enabled attribute is false, which is precisely why locking a deployed tag is worth the extra pipeline step.
The untagged-manifest retention policy[8] is the hands-off route, a preview feature of Premium registries. The registry keeps count of how many tags point at each manifest, a technique called reference counting; when a manifest becomes untagged and the policy is enabled and the manifest's delete-enabled attribute is true, the registry schedules a delete for a date and time derived from the configured window. The default period is seven days and you can set any value from 0 to 365, where 0 removes untagged manifests as soon as they become untagged. Its only selection knob is that window in days.
Enabling the untagged-manifest retention policy
az acr config retention update --registry myregistry \
--status enabled --days 30 --type UntaggedManifests
Two boundaries matter more than the syntax. The policy applies only to untagged manifests with timestamps after it is enabled, so switching it on does nothing about the backlog already in the registry. And it supports Docker manifest media types only; untagged OCI manifests such as application/vnd.oci.image.manifest.v1+json are not covered, and cleaning those up is a job for acr purge.
Soft delete is the undo, not a fourth route
The soft delete policy[9] is preview, is available in all service tiers, and does the opposite job: rather than removing artifacts, it holds deleted ones so you can get them back. With it enabled, deleted manifests and tags become soft-deleted artifacts you can list, filter, and restore for a retention period between 1 and 90 days, defaulting to seven. An autopurge runs every 24 hours and always applies the current retention value, so extending the window rescues artifacts deleted earlier that have not yet expired.
Enabling soft delete, then restoring an artifact
az acr config soft-delete update -r myregistry --days 7 --status enabled
az acr manifest list-deleted -r myregistry -n hello-world
az acr manifest restore -r myregistry -n hello-world:latest -d sha256:abc123
Three limitations decide whether it fits. Soft-deleted artifacts are billed at your active tier's storage pricing, so recovery is not free. The policy does not support registries configured for geo-replication or artifact cache. And Azure Container Registry does not allow the retention policy and the soft delete policy to be enabled at the same time, which turns cleanup into a genuine choice: automatic removal of untagged manifests, or an undo window, not both.
The one warning to internalise
Deploying by digest and purging untagged manifests are each good advice, and together they are a trap. Microsoft states it plainly on both the purge and retention pages: if you have systems that pull images by manifest digest rather than by image name, do not purge untagged images or set a retention policy for untagged manifests, because deleting those manifests is exactly what stops such systems from pulling. There is no contradiction with this page's first principle, only a division of labour: pin the pull with a unique tag so the manifest always has a tag protecting it, and reserve raw digest references for cases where you also control the cleanup policy. That is why unique tagging, not digest pinning, is the recommendation Microsoft points you to in both warnings.
Exam-pattern recognition
Questions on this objective rarely ask you to recite a command. They describe a symptom and expect you to name the mechanism that causes or cures it, so the useful preparation is mapping symptoms to mechanisms.
"Two nodes in the same deployment are running different code." The deployment references a stable tag, and it moved between the first pull and the scale-out. The fix is a unique per-build tag, or a manifest digest. Distractors offering more replicas, a different registry tier, or geo-replication address availability, not identity.
"Guarantee the exact image that was tested is the one that runs." Deploy by digest, myrepo@sha256:..., because the digest is derived from the image content itself and cannot be re-pointed. A version-looking tag such as v1.2 is the intended trap: it can be repushed at any moment, so it looks immutable and is not.
"Stop anyone overwriting or deleting a released image." az acr repository update --image myrepo:tag --write-enabled false. If the stem says updates must still be allowed but deletion must not, the answer switches to --delete-enabled false. If the stem mentions the Azure portal's Locks blade or az lock, it is describing a resource lock on the registry, which protects management operations and not repository data.
"Copy a public base image into our registry from a build agent with no Docker installed." az acr import. The distractors are almost always docker pull followed by docker tag and docker push, which need a daemon, and geo-replication, which duplicates a whole registry across regions rather than copying one image in.
"Registry storage keeps growing even though we delete old tags." Untagging is not deleting. The manifests are still there and still billed. The cure is acr purge --untagged, a Premium untagged-manifest retention policy, or a delete by digest. A distractor suggesting a larger service tier treats the symptom.
"We enabled the retention policy but the old untagged manifests are still there." The policy applies only to manifests untagged after it was enabled, and only to Docker manifest media types. Clearing an existing backlog, or untagged OCI artifacts, is a job for acr purge.
"Someone deleted a production image by mistake." Only the soft delete policy can recover it, and only if it was enabled before the deletion, with the retention window still open. Remember that soft delete and the untagged-manifest retention policy cannot both be enabled on the same registry, so a stem that says both are on is describing an impossible configuration.
One habit closes most of these: read the stem for whether it is talking about a label or about content. Tag questions are about naming and mutability, digest questions are about identity, and storage questions are about what the manifest still references after the label is gone.
Three ways to remove image data from a registry
| Consideration | Delete by digest | acr purge task | Untagged-manifest retention policy |
|---|---|---|---|
| What it removes | One manifest, its unique layers, and every tag pointing at it | Tags matching a filter, plus untagged manifests when you pass --untagged | Untagged manifests only, and their layer data |
| How it runs | One az acr repository delete call you issue | An ACR task, on demand or on a cron schedule | A registry policy the service applies on its own |
| Selection criteria | An explicit digest you looked up first | Repository and tag regular expressions plus an --ago age | Age in days, 0 to 365, default 7 |
| Availability | Generally available | Preview | Preview, Premium registries only |
| Effect of a lock | Blocked when write-enabled or delete-enabled is false | Skips a tag or repository with write-enabled false | Skips a manifest with delete-enabled false |
| Catch to remember | Deleting a digest deletes every tag pointing at it | Deletes tags only unless you add --untagged | Covers only manifests untagged after you enable it, Docker media types only |
Decision tree
Sharp facts the exam loves — give these one last read before exam day.
Cheat sheet
Sharp facts the exam loves — scan these before test day.
- Image digests are immutable, content-addressable identifiers
A manifest digest is a unique SHA-256 hash of the image's manifest, and every image or artifact, tagged or not, has its own, so referencing an image as repository@sha256:... always resolves to the exact same build even if a tag is later moved. Deploying by digest guarantees predictable, immutable image selection.
Trap Assuming a version-string tag is just as immutable as a digest.
9 questions test this
- Your compliance process requires evidence that the image running in an Azure Kubernetes Service production namespace is the exact artifact your image scan approved. The scan was run against a reposito
- You promote a validated image from a development Azure Container Registry to a production registry by using the registry's import capability. The development pipeline keeps repushing its version tags
- In an Azure Container Registry repository, a single manifest currently carries the tags v3, latest, and beta. QA asks you to stop the beta name from resolving so that no pipeline can pull the image un
- You operate a Python inference API on Azure Container Apps that pulls its image from Azure Container Registry. A regression appears hours after a release, and the release record identifies the build t
- Your team deploys an Azure Container Apps microservice from Azure Container Registry, and the app scales out to several replicas that pull the image at different moments. Every replica must run identi
- A build pipeline has repushed the same tag in an Azure Container Registry repository for months, and registry storage keeps growing even though the repository lists only a handful of tags. You must re
- A production Azure Kubernetes Service workload runs an image that your registry stores under the tag 2026.03.14. You must stop the release pipeline from overwriting or deleting that specific image, wh
- A nightly ACR task repushes the same tag, and your registry has filled with orphaned manifests. You plan to enable automatic cleanup of untagged manifests, but the Azure Kubernetes Service deployments
- An ACR task builds your application image on every source commit and has run successfully many times. Its Dockerfile FROM statement references a base image in the same registry by a unique per-build t
- Tags are mutable pointers that can be reassigned
An ACR tag, including a version-looking tag such as v1.2, can be repushed to point at a different manifest at any time, so deploying by tag does not guarantee a reproducible build.
12 questions test this
- Your team deploys an Azure Container Apps API from Azure Container Registry, and the container template always references the image with the latest tag. Operators cannot tell which commit a running re
- Your compliance process requires evidence that the image running in an Azure Kubernetes Service production namespace is the exact artifact your image scan approved. The scan was run against a reposito
- A developer pushed a test build from a workstation to your Azure Container Registry repository without specifying a tag in the push command. Shortly afterwards, the Azure Container Apps job that pulls
- You promote a validated image from a development Azure Container Registry to a production registry by using the registry's import capability. The development pipeline keeps repushing its version tags
- In an Azure Container Registry repository, a single manifest currently carries the tags v3, latest, and beta. QA asks you to stop the beta name from resolving so that no pipeline can pull the image un
- You operate a Python inference API on Azure Container Apps that pulls its image from Azure Container Registry. A regression appears hours after a release, and the release record identifies the build t
- Your team deploys an Azure Container Apps microservice from Azure Container Registry, and the app scales out to several replicas that pull the image at different moments. Every replica must run identi
- A build pipeline has repushed the same tag in an Azure Container Registry repository for months, and registry storage keeps growing even though the repository lists only a handful of tags. You must re
- A production Azure Kubernetes Service workload runs an image that your registry stores under the tag 2026.03.14. You must stop the release pipeline from overwriting or deleting that specific image, wh
- An ACR task builds your Python service image, and its Dockerfile FROM statement references python:latest in a public registry. Two requirements now apply: the build must not move to a new major runtim
- A nightly ACR task repushes the same tag, and your registry has filled with orphaned manifests. You plan to enable automatic cleanup of untagged manifests, but the Azure Kubernetes Service deployments
- An ACR task builds your application image on every source commit and has run successfully many times. Its Dockerfile FROM statement references a base image in the same registry by a unique per-build t
- The latest tag floats to the most recent push that carries it
The latest tag is simply the tag Docker and the registry assume when a command names none, so it moves only when a push actually carries it and not whenever any newer image is pushed. Because it is reused rather than unique it is a stable tag, and Microsoft's tagging guidance is to avoid deploying from stable tags because they keep receiving updates.
Trap Believing latest always points to the highest semantic version.
5 questions test this
- Your team deploys an Azure Container Apps API from Azure Container Registry, and the container template always references the image with the latest tag. Operators cannot tell which commit a running re
- A developer pushed a test build from a workstation to your Azure Container Registry repository without specifying a tag in the push command. Shortly afterwards, the Azure Container Apps job that pulls
- Your team deploys an Azure Container Apps microservice from Azure Container Registry, and the app scales out to several replicas that pull the image at different moments. Every replica must run identi
- An ACR task builds your Python service image, and its Dockerfile FROM statement references python:latest in a public registry. Two requirements now apply: the build must not move to a new major runtim
- A nightly ACR task repushes the same tag, and your registry has filled with orphaned manifests. You plan to enable automatic cleanup of untagged manifests, but the Azure Kubernetes Service deployments
- Unique per-build tags enable traceable rollback
Best practice is to tag each build with a unique value such as a build ID or Git commit hash, so any deployed version is traceable and you can roll back to an exact, unchanged image.
7 questions test this
- You run a Python scoring API on Azure Kubernetes Service with cluster autoscaling enabled, and its deployment references an image in Azure Container Registry by a tag that the release pipeline reuses
- Your Azure Kubernetes Service deployments reference their images in Azure Container Registry by manifest digest, and the registry is close to its storage limit. You plan to enable automated cleanup of
- Two teams push AI service images into one shared Azure Container Registry: the API team builds with Jenkins and the web team builds with Azure Pipelines. Both systems emit incrementing build numbers w
- A production revision of your Azure Container Apps AI service is failing. Every image the pipeline has pushed to Azure Container Registry carries a unique tag that contains the build number, and no ta
- Your platform team publishes a shared Python base image that application teams reference in their Dockerfiles, and it must keep receiving security servicing under the same reference. The application t
- You develop a Python inference API that an Azure Pipelines workflow builds and pushes to Azure Container Registry before deploying it to Azure Container Apps. After a bad release, the team must identi
- Your team builds a Python container image with a multi-step ACR task that is triggered both by commits to the main branch and by base image updates. Every run must push the image under a tag that no e
- Stable tags roll forward for base-image patching
A stable tag such as major.minor is deliberately re-pointed to the newest patched build so images that consume it pick up OS and framework fixes; it trades reproducibility for automatic patching and is typically used on base images, not deployments.
- Locking a tag or manifest prevents overwrite or delete
Running az acr repository update against one tag (--image myrepo:tag) or manifest digest (--image myrepo@sha256:...) sets that image's lock attributes: --write-enabled false makes it immutable so it can be neither overwritten nor deleted, while --delete-enabled false blocks only deletion and still allows the image to be updated. Locking a released production image protects it from accidental change.
Trap Assuming --delete-enabled false also stops the image from being overwritten.
6 questions test this
- You release a Python model-serving image from Azure Container Registry to Azure Container Apps. Another team's pipeline has twice pushed different content under the tag that your production revision r
- A security scan flags one released AI inference image version already stored in Azure Container Registry as containing a vulnerable library. Until the investigation closes, no cluster or app may pull
- Your registry has the untagged-manifest retention policy enabled. One production deployment still pulls an image by manifest digest, and that manifest became untagged when the release pipeline moved i
- A release engineer protected the production tag of an AI gateway image in Azure Container Registry by setting delete-enabled to false on that tag and confirmed the attribute. A cleanup script that add
- A compliance rule states that the container image behind your production AI endpoint must never be removed from Azure Container Registry, while the platform team still needs to push corrected content
- Your organization keeps a repository of released, audited AI runtime images in Azure Container Registry. Every image currently in that repository must be protected from being overwritten or deleted, a
- az acr import copies images server-side without Docker
az acr import pulls an image from another registry (Docker Hub, MCR, or another ACR) directly into the target registry, so it needs no local Docker daemon and no docker pull followed by docker push.
Trap Thinking the image has to be pulled locally and pushed again to land in the target registry.
10 questions test this
- A release pipeline uses a managed identity to import images from a shared base-image registry into your team's Azure Container Registry, and both registries are in the same Microsoft Entra tenant. The
- Your team runs an AI orchestration component on Windows containers, but every workstation and pipeline host in the environment runs Linux and has no container runtime installed. A Windows Server Core
- A vendor hosts a validated retrieval model image in a private non-Azure container registry and gives you a user name and access token with pull rights, plus the digest of the exact build your complian
- A release step imports a very large model-serving image from a partner Azure Container Registry into your production registry in the same tenant. The step must not hold the release pipeline open while
- You are standardizing on an official multi-architecture image from Docker Hub for an inference sidecar that must run on both AMD64 and ARM64 node pools. The image must be served from your Azure Contai
- Your production Azure Container Registry was recently moved behind a private endpoint, and a hardening change disabled its firewall exceptions. Imports from the development registry that previously su
- Your platform team stores the Helm 3 chart that deploys your inference API as an OCI artifact in a staging Azure Container Registry. The identical chart artifact must be published to the production re
- A partner organization publishes a model-serving image in an Azure Container Registry that belongs to a different Microsoft Entra tenant from yours. Your identity has no role assignment in that tenant
- You import images from a shared source Azure Container Registry that lives in another subscription in the same Microsoft Entra tenant. Security has just disabled public network access on that source r
- You develop a Python inference service that must be built on a Microsoft-published base image. Your continuous integration agents run a hardened OS image with no Docker Engine installed, no daemon may
- Import by digest to preserve an exact build
Importing with source repository@sha256:... rather than by tag copies a specific immutable manifest, guaranteeing the imported image is byte-identical to the intended source build.
Trap Assuming az acr import only works with publicly accessible source images.
5 questions test this
- A vendor hosts a validated retrieval model image in a private non-Azure container registry and gives you a user name and access token with pull rights, plus the digest of the exact build your complian
- Your QA team signs off on a specific build of an inference API image that sits in a development Azure Container Registry under the stable tag 2.4, a tag the build system reassigns whenever it services
- Your governance policy states that images promoted into the production Azure Container Registry must never carry a human-assigned tag, so that deployments can reference them only by content address. Y
- Your team imports a public Python base image from Docker Hub into Azure Container Registry with each release, always naming the tag 3.12-slim. Auditors report that two releases built from identical ap
- A regression reaches production after a base-image refresh. The previous, known-good build is still in the source Azure Container Registry, but the tag that once pointed to it was reassigned to the ne
- Deleting a tag leaves the manifest consuming storage
Removing or overwriting a tag does not delete the underlying manifest and layers; the resulting untagged (dangling) manifest keeps consuming registry storage until it is explicitly purged.
Trap Thinking that untagging an image reclaims its storage.
8 questions test this
- Your team's build pipeline pushes a Python API image to an Azure Container Registry repository under the same stable tag several times a day. The repository still lists a single tag, yet the registry'
- You are auditing an Azure Container Registry before a cost review. The Azure portal's repository view lists only a handful of tags per repository, but the registry consumes far more storage than those
- An Azure Container Registry holds several Python model-serving images that were all built from the same base image. You delete one untagged manifest whose image size is reported as roughly two gigabyt
- You are cleaning up an Azure Container Registry repository that holds test builds of a document-ingestion service. You need one operation that removes a specific test image, frees the layers unique to
- A Premium Azure Container Registry has accumulated years of untagged manifests from stable-tag rebuilds. You enable the untagged-manifest retention policy and wait past the retention period, but the o
- You schedule an acr purge task that removes tags older than a set age from your Azure Container Registry's development repositories. The task reports many deleted tags each week, yet the registry's st
- You plan to schedule automatic deletion of untagged manifests in an Azure Container Registry that serves an AI inference platform, but several AKS deployments pin images by manifest digest rather than
- You maintain an Azure Container Registry that backs a Python inference service. To cut storage cost, a colleague removed the tags from dozens of obsolete builds, but the registry overview still report
- acr purge and retention policies remove stale images
An acr purge command, usually run as a scheduled ACR Task, deletes tags that match a repository and tag regex (--filter) and are older than a duration (--ago), and by default it removes only the tag references, so --untagged is needed to delete the dangling manifests too. A Premium-tier retention policy is the filter-free alternative, automatically deleting every untagged manifest a set number of days after it becomes untagged.
Trap Expecting a plain acr purge to reclaim the manifests behind the tags it deleted.
9 questions test this
- Your Premium Azure Container Registry stores both Docker container images and OCI artifacts such as the Helm charts that your AI deployment pipeline pushes. The registry's untagged-manifest retention
- Your organization wants Azure Container Registry to delete untagged manifests automatically a fixed number of days after they lose their tags, as a registry-wide setting with no task, schedule, or fil
- Your team stores development images for an AI service in an Azure Container Registry, and the repositories fill with builds that nobody deploys. You need registry cleanup to run every week with no sou
- A Premium Azure Container Registry has the untagged-manifest retention policy enabled. One base image manifest is intentionally untagged and is pulled by digest by several build pipelines, so it must
- You are cleaning up an Azure Container Registry repository that holds test builds of a document-ingestion service. You need one operation that removes a specific test image, frees the layers unique to
- A Premium Azure Container Registry has accumulated years of untagged manifests from stable-tag rebuilds. You enable the untagged-manifest retention policy and wait past the retention period, but the o
- You schedule an acr purge task that removes tags older than a set age from your Azure Container Registry's development repositories. The task reports many deleted tags each week, yet the registry's st
- You plan to schedule automatic deletion of untagged manifests in an Azure Container Registry that serves an AI inference platform, but several AKS deployments pin images by manifest digest rather than
- You maintain an Azure Container Registry that backs a Python inference service. To cut storage cost, a colleague removed the tags from dozens of obsolete builds, but the registry overview still report
- Soft delete allows recovery of deleted artifacts
When the soft-delete policy is enabled, deleted manifests and tags are retained for a configurable window and can be restored before they are permanently removed.
References
- About registries, repositories, images, and artifacts
- Understanding image layers
- Recommendations for tagging and versioning container images
- Lock a container image in an Azure container registry
- Import container images to a container registry
- Delete container images in Azure Container Registry
- Automatically purge images from an Azure container registry
- Set a retention policy for untagged manifests
- Recover deleted artifacts with the soft delete policy