What is the problem you're trying to solve
Several Azure services that consume container images from an ACR require the referenced image to exist at the moment the consuming resource is deployed. Azure Container Apps is the clearest example: deploying a Container App that points at myacr.azurecr.io/my-image:latest fails if my-image:latest is not already in the registry. This is a known and long-standing pain point (see microsoft/azure-container-apps#646).
The realistic workflow is:
- Day 0 - infrastructure deployment. Bicep / ARM / Terraform creates the ACR, the Container App environment, the Container App, networking, identity, etc. The application image (
my-image:latest) does not exist yet because there is nothing in the pipeline that has built and pushed it.
- Day 0+1 - CI/CD. The application's build pipeline produces the real
my-image:latest and pushes it into the ACR. From then on, every revision update is a normal containerapp update --image.
Step 1 cannot complete today, because the Container App resource refuses to provision against an image path that does not resolve. The infra deploy fails, even though everything downstream of "image gets pushed" would work.
The current workarounds all break the pure-IaC story:
- Two-stage deployment - deploy ACR, run an out-of-band
docker push of a dummy image, then deploy the consumers. Requires orchestration outside the template.
- The community
br/public:deployment-scripts/import-acr module, which provisions a Microsoft.Resources/deploymentScripts resource that spins up an Azure Container Instance, assigns it a managed identity, grants it AcrPush, runs the Azure CLI to import a public image and re-tag it, and tears itself down. It works, but it adds a UAMI, a role assignment, an ACI, and a storage account to every deployment, takes minutes per import, and is a script wrapped around what should be a first-class RP capability.
Microsoft.ContainerRegistry/registries/importImage/action - exists, but it's an imperative POST action, not a declarative child resource that can sit in a Bicep / ARM template alongside the registry.
- ACR Transfer (
importPipelines / exportPipelines / pipelineRuns) - declarative but designed for ACR-to-ACR transfer with a backing storage account; not appropriate for "make sure my-image:latest exists in this empty registry."
The result is that the most common "Container Apps + ACR" quick-start cannot be expressed as a single Bicep file, despite both services supporting Bicep individually.
Describe the solution you'd like
Let the ACR resource declare a list of placeholder images at user-chosen repository:tag paths, where the content comes from a curated set of small Microsoft-published quick-start images (e.g. aci-helloworld). The user picks the destination name to match what their CI/CD will push later; the content is just a stand-in so the path resolves.
A possible shape:
resource acr 'Microsoft.ContainerRegistry/registries@2026-xx-xx' = {
name: acrName
location: location
sku: { name: 'Basic' }
properties: {
adminUserEnabled: false
placeholderImages: [
{
// The user-chosen path that downstream resources will reference.
// CI/CD will overwrite this tag later with the real image.
target: 'my-image:latest'
// Curated, Microsoft-published stand-in content. Small, safe,
// already on MAR, no licensing or external egress concerns.
source: 'aci-helloworld'
}
{
target: 'my-api:v1'
source: 'aci-helloworld'
}
]
}
}
resource app 'Microsoft.App/containerApps@2025-xx-xx' = {
name: 'my-app'
// ...
properties: {
template: {
containers: [
{
name: 'my-app'
// Resolves on day 0 because the placeholder exists.
// Resolves correctly on day 1+ because CI/CD has overwritten the tag.
image: '${acr.properties.loginServer}/my-image:latest'
}
]
}
}
}
The mental model is deliberately narrow:
- The user picks the destination
repository:tag - it must match what their pipeline will push later, otherwise the placeholder is useless.
- The content is a Microsoft-curated stand-in - chosen from a short list (
aci-helloworld, nginx-hello, an empty scratch image, etc.) that ACR knows how to materialise without the customer providing credentials, configuring network access to MAR / Docker Hub, or running any compute.
- It's a one-shot seed, not a sync. Once CI/CD pushes the real image, the placeholder is gone. Re-running the template should be a no-op if the tag already exists (i.e. don't clobber the real image with the placeholder).
For a more general version, an additional imports child resource that targets arbitrary public sources (covered by Microsoft.ContainerRegistry/registries/importImage/action today) would also be welcome, but the placeholder-with-curated-content variant is the minimum needed to unblock the Container Apps + ACR + Bicep flow.
Acceptance criteria
- A new declarative property (or child resource) under
Microsoft.ContainerRegistry/registries that creates one or more placeholder images at user-specified repository:tag paths.
- Source content drawn from a small, Microsoft-published catalog so no customer credentials, outbound network egress, managed identity, or role assignments are required.
- Idempotent: if the target tag already exists (e.g. CI/CD has already pushed the real image), the placeholder is not written. Re-deployments do not regress the registry to the placeholder.
- Surfaces in the auto-generated Bicep / ARM / AzAPI / Terraform schemas via the normal REST spec pipeline (
Azure/azure-rest-api-specs -> Azure/bicep-types-az).
- Compatible with private endpoints and ABAC-enabled registries (the seeding happens server-side inside ACR, so no client-side network reachability is required).
Additional context
- Related, but does not solve this:
Microsoft.ContainerRegistry/registries/importImage/action - imperative, not part of the deployment graph, requires a source URL and credentials, not a curated catalog.
Microsoft.ContainerRegistry/registries/importPipelines + exportPipelines + pipelineRuns - aimed at ACR-to-ACR transfer with a backing storage account, not at seeding from a curated catalog.
- Current community workaround:
br/public:deployment-scripts/import-acr in Azure/bicep-registry-modules.
- Downstream pain points this would close:
microsoft/azure-container-apps#646 - Container Apps deployment fails when the image is not yet in the registry.
- The standard "Container Apps + ACR" quick-start cannot be expressed as a single Bicep file today.
- Reasonable catalog of curated stand-in images (already Microsoft-published on MAR, small, and harmless):
mcr.microsoft.com/azuredocs/aci-helloworld
mcr.microsoft.com/azuredocs/containerapps-helloworld
mcr.microsoft.com/k8se/quickstart
What is the problem you're trying to solve
Several Azure services that consume container images from an ACR require the referenced image to exist at the moment the consuming resource is deployed. Azure Container Apps is the clearest example: deploying a Container App that points at
myacr.azurecr.io/my-image:latestfails ifmy-image:latestis not already in the registry. This is a known and long-standing pain point (seemicrosoft/azure-container-apps#646).The realistic workflow is:
my-image:latest) does not exist yet because there is nothing in the pipeline that has built and pushed it.my-image:latestand pushes it into the ACR. From then on, every revision update is a normalcontainerapp update --image.Step 1 cannot complete today, because the Container App resource refuses to provision against an image path that does not resolve. The infra deploy fails, even though everything downstream of "image gets pushed" would work.
The current workarounds all break the pure-IaC story:
docker pushof a dummy image, then deploy the consumers. Requires orchestration outside the template.br/public:deployment-scripts/import-acrmodule, which provisions aMicrosoft.Resources/deploymentScriptsresource that spins up an Azure Container Instance, assigns it a managed identity, grants itAcrPush, runs the Azure CLI to import a public image and re-tag it, and tears itself down. It works, but it adds a UAMI, a role assignment, an ACI, and a storage account to every deployment, takes minutes per import, and is a script wrapped around what should be a first-class RP capability.Microsoft.ContainerRegistry/registries/importImage/action- exists, but it's an imperative POST action, not a declarative child resource that can sit in a Bicep / ARM template alongside the registry.importPipelines/exportPipelines/pipelineRuns) - declarative but designed for ACR-to-ACR transfer with a backing storage account; not appropriate for "make suremy-image:latestexists in this empty registry."The result is that the most common "Container Apps + ACR" quick-start cannot be expressed as a single Bicep file, despite both services supporting Bicep individually.
Describe the solution you'd like
Let the ACR resource declare a list of placeholder images at user-chosen
repository:tagpaths, where the content comes from a curated set of small Microsoft-published quick-start images (e.g.aci-helloworld). The user picks the destination name to match what their CI/CD will push later; the content is just a stand-in so the path resolves.A possible shape:
The mental model is deliberately narrow:
repository:tag- it must match what their pipeline will push later, otherwise the placeholder is useless.aci-helloworld,nginx-hello, an empty scratch image, etc.) that ACR knows how to materialise without the customer providing credentials, configuring network access to MAR / Docker Hub, or running any compute.For a more general version, an additional
importschild resource that targets arbitrary public sources (covered byMicrosoft.ContainerRegistry/registries/importImage/actiontoday) would also be welcome, but the placeholder-with-curated-content variant is the minimum needed to unblock the Container Apps + ACR + Bicep flow.Acceptance criteria
Microsoft.ContainerRegistry/registriesthat creates one or more placeholder images at user-specifiedrepository:tagpaths.Azure/azure-rest-api-specs->Azure/bicep-types-az).Additional context
Microsoft.ContainerRegistry/registries/importImage/action- imperative, not part of the deployment graph, requires a source URL and credentials, not a curated catalog.Microsoft.ContainerRegistry/registries/importPipelines+exportPipelines+pipelineRuns- aimed at ACR-to-ACR transfer with a backing storage account, not at seeding from a curated catalog.br/public:deployment-scripts/import-acrinAzure/bicep-registry-modules.microsoft/azure-container-apps#646- Container Apps deployment fails when the image is not yet in the registry.mcr.microsoft.com/azuredocs/aci-helloworldmcr.microsoft.com/azuredocs/containerapps-helloworldmcr.microsoft.com/k8se/quickstart