Summary
When using the azure-prepare or azure-deploy skills to deploy a containerized app to Azure Container Apps via azd + Bicep, users are often confused by the placeholder container image (mcr.microsoft.com/azuredocs/containerapps-helloworld) that appears after provisioning. The skills should proactively explain this behavior and guide users through it.
Problem
azd uses a two-phase deployment lifecycle for Azure Container Apps:
azd provision — Creates infrastructure via Bicep. ARM requires a container image at resource-creation time, but the user's app image typically doesn't exist yet (especially with remote Docker builds). So azd scaffolds Bicep that uses a placeholder: mcr.microsoft.com/azuredocs/containerapps-helloworld.
azd deploy — Builds code, pushes to ACR, and updates the Container App with the user's real image.
This is by design (source), but creates several pain points:
- Users who run
azd provision alone see the placeholder and think the deployment failed
- Re-provisioning can reset a previously deployed image back to the placeholder if the Bicep
exists parameter isn't wired correctly via fetch-container-image.bicep
- Users who already have a pre-built image in ACR don't know they can skip the build by setting
docker.image / docker.registry / docker.tag in azure.yaml, or by setting SERVICE_<NAME>_IMAGE_NAME via azd env set
- The per-service Bicep "controlled-revision deployment" (
infra/<serviceName>.bicep) approach — the recommended production pattern — is not surfaced
Proposed Improvements
1. Proactive guidance during Container Apps provisioning
When the skill generates Bicep for an ACA deployment, explain that:
- A placeholder image will be used during provisioning (this is expected)
azd deploy (or azd up) must follow to deploy the real image
- The placeholder gets auto-deactivated after deploy
2. Wire the exists parameter correctly in generated Bicep
Ensure generated Bicep templates include:
- The
fetch-container-image.bicep module
- The
param exists bool parameter fed by SERVICE_<NAME>_RESOURCE_EXISTS
- Conditional logic so re-provisions preserve the running image
3. Support pre-built image scenarios
When a user says "I already have an image" or "deploy this image from ACR", the skill should:
- Set
docker.image, docker.registry, and docker.tag in azure.yaml
- Or guide the user to
azd env set SERVICE_<NAME>_IMAGE_NAME myacr.azurecr.io/my-app:v1
4. Surface the controlled-revision deployment pattern
For production deployments, recommend creating infra/<serviceName>.bicep (+ .parameters.json) so azd deploy uses atomic single-revision deployment instead of the two-phase placeholder dance.
5. Troubleshooting table in skill knowledge
Add awareness of common ACA + azd pitfalls:
| Problem |
Cause |
Fix |
| Placeholder image after provision |
Normal — deploy hasn't run |
Run azd deploy or azd up |
| Image resets on re-provision |
exists param missing in Bicep |
Wire fetch-container-image.bicep |
| "Container registry not found" |
AZURE_CONTAINER_REGISTRY_ENDPOINT not set |
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT myacr.azurecr.io |
| ACR auth errors |
Missing AcrPull role |
Assign AcrPull to the Container App's managed identity |
| Sidecars not updated |
azd deploy only updates containers[0].image |
Use per-service Bicep |
References
Summary
When using the
azure-prepareorazure-deployskills to deploy a containerized app to Azure Container Apps viaazd+ Bicep, users are often confused by the placeholder container image (mcr.microsoft.com/azuredocs/containerapps-helloworld) that appears after provisioning. The skills should proactively explain this behavior and guide users through it.Problem
azduses a two-phase deployment lifecycle for Azure Container Apps:azd provision— Creates infrastructure via Bicep. ARM requires a container image at resource-creation time, but the user's app image typically doesn't exist yet (especially with remote Docker builds). So azd scaffolds Bicep that uses a placeholder:mcr.microsoft.com/azuredocs/containerapps-helloworld.azd deploy— Builds code, pushes to ACR, and updates the Container App with the user's real image.This is by design (source), but creates several pain points:
azd provisionalone see the placeholder and think the deployment failedexistsparameter isn't wired correctly viafetch-container-image.bicepdocker.image/docker.registry/docker.taginazure.yaml, or by settingSERVICE_<NAME>_IMAGE_NAMEviaazd env setinfra/<serviceName>.bicep) approach — the recommended production pattern — is not surfacedProposed Improvements
1. Proactive guidance during Container Apps provisioning
When the skill generates Bicep for an ACA deployment, explain that:
azd deploy(orazd up) must follow to deploy the real image2. Wire the
existsparameter correctly in generated BicepEnsure generated Bicep templates include:
fetch-container-image.bicepmoduleparam exists boolparameter fed bySERVICE_<NAME>_RESOURCE_EXISTS3. Support pre-built image scenarios
When a user says "I already have an image" or "deploy this image from ACR", the skill should:
docker.image,docker.registry, anddocker.taginazure.yamlazd env set SERVICE_<NAME>_IMAGE_NAME myacr.azurecr.io/my-app:v14. Surface the controlled-revision deployment pattern
For production deployments, recommend creating
infra/<serviceName>.bicep(+.parameters.json) soazd deployuses atomic single-revision deployment instead of the two-phase placeholder dance.5. Troubleshooting table in skill knowledge
Add awareness of common ACA + azd pitfalls:
azd deployorazd upexistsparam missing in Bicepfetch-container-image.bicepAZURE_CONTAINER_REGISTRY_ENDPOINTnot setazd env set AZURE_CONTAINER_REGISTRY_ENDPOINT myacr.azurecr.ioAcrPullroleAcrPullto the Container App's managed identityazd deployonly updatescontainers[0].imageReferences