Azure Containers for AZ-104: ACR, Container Instances and Container Apps
Introduction
Azure container management for AZ-104 connects private image storage, Container Instances and Container Apps sizing and scaling. This lesson continues the skills area Deploy and manage Azure compute resources (20–25% of the exam). The study guide objective is provision and manage containers in the Azure portal: create and manage an Azure container registry, provision a container by using Azure Container Instances, provision a container by using Azure Container Apps, and manage sizing and scaling for containers, including Azure Container Instances and Azure Container Apps.
A container packages an application with its libraries so that it runs identically on a laptop, in a test environment and in production. As an Azure administrator you are rarely asked to write the application; you are asked to store the image safely, choose the right place to run it, give it the right CPU and memory, and make it scale. Exam questions are scenarios: a team has an image, a traffic pattern and a constraint (cost, network isolation, scale to zero, run once and exit), and you pick the service or setting that fits.
After this lesson you will be able to choose the right registry tier, push and pull images, run a one-off or long-lived container in Azure Container Instances (ACI), deploy a microservice to Azure Container Apps with ingress and scaling rules, and explain how each service is sized and scaled.
Learning objectives
- Explain what Azure Container Registry (ACR) stores and compare the Basic, Standard and Premium tiers.
- Authenticate to a registry securely and push, pull and import images.
- Create a container group in ACI, set CPU, memory, restart policy and environment variables, and mount a volume.
- Create a Container Apps environment and container app, configure ingress, revisions and secrets.
- Configure Container Apps scale rules (HTTP, queue, CPU, memory) and minimum and maximum replicas.
- Choose between ACI, Container Apps and App Service for a given requirement.
Azure Container Registry
What a registry does
A container registry is a private store for container images and related artifacts (for example Helm charts). Azure Container Registry is the managed, Docker-compatible registry service. Images use the registry's actual login server, followed by <repository>:<tag> or an immutable digest. Domain Name Label protection can add a hash to the DNS name, so retrieve loginServer rather than assuming it always equals <registry>.azurecr.io. The registry name is globally unique, 5 to 50 alphanumeric characters (use lowercase in CLI commands), because it becomes part of the login server DNS name.
Why a private registry instead of pulling from a public hub? Control and proximity: you decide who can push and pull, you can place images near workloads to reduce latency, while still accounting for replication, network and transfer charges, and you can scan, replicate and lock them.
Service tiers
| Feature | Basic | Standard | Premium |
|---|---|---|---|
| Intended use | Learning, low volume | Most production workloads | High volume, enterprise |
| Included storage | 10 GiB | 100 GiB | 500 GiB |
| Geo-replication | No | No | Yes |
| Private endpoints (Private Link) | No | No | Yes |
| Zone redundancy | Yes (supported regions) | Yes | Yes |
| Customer-managed keys | No | No | Yes |
Docker Content Trust is a legacy Premium feature scheduled for removal on March 31, 2028; review Notary Project/Notation guidance for new signing designs. Storage beyond the included amount is billed per GiB. Throughput (read and write operations per minute and bandwidth) rises with each tier. You can change tier at any time; moving from Premium down requires removing Premium-only configuration such as geo-replications first.
Exam tip: "Replicate the registry to several regions" or "restrict the registry to a private endpoint" means Premium. Nothing else in the registry tier list offers those.
Authenticating to a registry
| Method | Typical user | Notes |
|---|---|---|
Microsoft Entra identity (az acr login) |
Developers, administrators | Uses your signed-in identity and Azure RBAC |
| Service principal | CI/CD pipelines | Assign a role scoped to the registry |
| Managed identity | Azure services pulling images | Best practice: no secret to rotate |
| Repository-scoped tokens | Limited external access | Fine-grained, can be limited to specific repositories |
| Admin account | Quick tests only | Single shared username and password; disabled by default |
First inspect the registry's role assignment permissions mode. In RBAC Registry Permissions mode, use AcrPull, AcrPush or AcrDelete at registry scope. In RBAC Registry + ABAC Repository Permissions mode, those legacy roles are not honored: use Container Registry Repository Reader, Writer or Contributor, optionally with repository conditions on the registry-scope assignment. Catalog listing is a separate role in ABAC mode. A runtime pulling a known image needs the appropriate read role, not subscription Contributor.
Working with images
# Create a Premium registry in a region close to the workloads
az acr create --resource-group rg-containers --name contosoacr001 --sku Premium \
--role-assignment-mode rbac
loginServer="$(az acr show --name contosoacr001 --query loginServer --output tsv)"
# Log in with your Entra identity
az acr login --name contosoacr001
# Tag and push a local image
docker tag shop-api:1.4 "$loginServer/shop/api:1.4"
docker push "$loginServer/shop/api:1.4"
# Build in the cloud without a local Docker daemon (ACR Tasks)
az acr build --registry contosoacr001 --image shop/api:1.5 .
# Import a public image into the registry
az acr import --name contosoacr001 \
--source mcr.microsoft.com/azuredocs/aci-helloworld:latest --image demos/helloworld:sampleThese Bash examples assume the resource group, local application image and Dockerfile build context already exist. The Docker push/login steps require a Docker client/daemon; az acr build and import do not. The imported latest image is a demo; pin approved production images by digest. az acr build runs the build on ACR Tasks, so a build server is unnecessary; the resulting image lands directly in the registry. az acr import copies an image between registries without pulling it to your machine.
Registry network access
By default a registry has a public endpoint. Premium supports public IP network rules and private endpoints. For private-only access, disable the public endpoint, configure private DNS and allow the workload's network path. ACR service-endpoint VNet access is a separate Premium preview feature; prefer the documented Private Link design when private-only access is required.
Azure Container Instances
The idea
Azure Container Instances runs containers directly on Azure without managing virtual machines or an orchestrator. You pay per second for the CPU and memory you allocate while the group runs. It starts in seconds and suits simple applications, build agents, event-driven bursts and batch jobs. It does not provide built-in autoscaling, load balancing across instances, rolling updates or service discovery. When those are required, think Container Apps.
Container groups
The deployment unit is the container group: one or more containers scheduled on the same host that share a lifecycle, local network and storage volumes. Containers in a group reach each other on localhost and must use different ports. Multi-container groups currently support Linux only; Windows groups contain a single container. A typical Linux pattern is an application container plus a log-shipping sidecar.
Key properties of a group:
- OS type: Linux or Windows (all containers in a group use the same OS).
- Resources: each container requests CPU and memory; the group total is what you are billed for. A limit, if set, must be at least the request.
- Restart policy:
Always(default),OnFailureorNever. It applies to the whole group. - Networking: a public IP with a DNS name label, or private addressing in a subnet delegated to
Microsoft.ContainerInstance/containerGroups. VNet groups do not support public IP/DNS labels; configure NAT Gateway on their subnet for supported outbound connectivity. Use a separate subnet for private endpoints. - Environment variables: plain or secure (secure values are not shown in the portal or API output).
- Volumes: Azure Files share, empty directory, Git repository or secret volume.
- Identity: system-assigned and/or user-assigned identity for Azure resource access. ACI image pulls from ACR require a user-assigned identity; system-assigned image-pull authentication is unsupported.
Restart policy and run-to-completion
| Policy | Behavior | Use case |
|---|---|---|
| Always | Restarts whenever a container stops | Web server, API |
| OnFailure | Restarts only on non-zero exit code | Job that should retry on error |
| Never | Runs once, never restarts | One-off batch or report |
With Never or OnFailure, once the container finishes successfully the group becomes Terminated and compute billing stops. With the default Always, a short-lived task would be restarted again and again, which is a classic mistake.
Creating a container group
az identity create --resource-group rg-containers --name id-container-pull
pullIdentityId="$(az identity show -g rg-containers -n id-container-pull --query id -o tsv)"
pullPrincipalId="$(az identity show -g rg-containers -n id-container-pull --query principalId -o tsv)"
registryId="$(az acr show -n contosoacr001 --query id -o tsv)"
az role assignment create --assignee-object-id "$pullPrincipalId" \
--assignee-principal-type ServicePrincipal --role AcrPull --scope "$registryId"
az container create \
--resource-group rg-containers --name aci-report \
--image "$loginServer/reports/generator:2.0" --os-type Linux \
--cpu 1 --memory 1.5 --restart-policy Never \
--assign-identity "$pullIdentityId" --acr-identity "$pullIdentityId" \
--environment-variables REPORT_DATE="$(date -u +%F)"The registry is explicitly in RBAC-only mode, the report image must already exist, and the caller needs permissions to create identities and role assignments. Allow role propagation before the private pull. For an ABAC registry use the repository read role instead. Pass application secrets through the documented secure settings or retrieve them using identity; never embed real passwords in the example.
Multi-container groups and limits are usually declared in a YAML file (az container create --file group.yaml) or an ARM/Bicep template. Fixed sizing is the rule: ACI does not resize a running group. To change CPU or memory you redeploy the group. To get more throughput you create more groups.
Pulling from ACR without secrets
Create a user-assigned identity first, grant AcrPull in RBAC-only mode (or the repository read role in ABAC mode), and specify the same identity in --assign-identity and --acr-identity. A private ACR endpoint must be on a different subnet from an ACI-delegated subnet. Avoid embedding the ACR admin password in a template.
Azure Container Apps
The idea
Azure Container Apps is a serverless container platform built on Kubernetes, KEDA and Envoy, but without exposing the cluster. You deploy containers and describe what they need; the platform handles scaling, HTTPS ingress, revisions and service-to-service communication. It is suited to microservices, APIs, background workers and event-driven processing.
Core building blocks
| Concept | Meaning |
|---|---|
| Environment | Secure boundary around one or more container apps and jobs. Apps share environment networking and a configured logging destination; Log Analytics is optional (Azure Monitor or no log destination are also supported). |
| Container app | The deployed application, made of one or more containers (plus optional init and sidecar containers). |
| Revision | An immutable snapshot of the app version. Changes to the container image or scale settings create a new revision. |
| Replica | A running instance of a revision. |
| Ingress | HTTPS or TCP endpoint, external (internet) or internal (environment only). |
| Jobs | Containers that run to completion, manually, on a schedule or on events. |
Workload profiles
An environment can use Consumption for per-replica serverless usage and Dedicated profiles billed by allocated profile instances. Configure app-replica and profile-instance limits separately; stopping app replicas does not by itself eliminate dedicated-profile management or infrastructure charges. Flexible/Flex is currently preview, offers larger memory options and dedicated networking, and does not support app scale-to-zero. Use the current profile/region table for eligibility.
Revisions and traffic splitting
Container Apps can run in single revision mode (only the latest receives traffic) or multiple revision mode (several are active and traffic is split by percentage). Multiple revision mode enables blue-green and canary releases: send 10% to the new revision, watch error rates, then shift to 100%.
Ingress, secrets and registries
- Ingress can be enabled with a target port. App external ingress publishes at the environment's inbound endpoint: public or private depending on the environment. App internal ingress directly exposes its FQDN only to that same Container Apps environment, not every client in the VNet. For VNet clients, use an internal environment with app external ingress. Environment-level HTTP routing can introduce additional paths; review it when enforcing isolation.
- Secrets are stored at the app level (or referenced from Azure Key Vault) and exposed to containers as environment variables or mounted volumes.
- Registry credentials: use a managed identity with AcrPull in RBAC-only mode or Container Registry Repository Reader in ABAC mode, rather than a stored password.
az containerapp env create --name cae-shop --resource-group rg-containers --location westeurope
az containerapp create \
--name shop-api \
--resource-group rg-containers \
--environment cae-shop \
--image "$loginServer/shop/api:1.4" \
--registry-server "$loginServer" \
--user-assigned "$pullIdentityId" --registry-identity "$pullIdentityId" \
--target-port 8080 --ingress external \
--cpu 0.5 --memory 1.0Gi \
--min-replicas 0 --max-replicas 10Sizing and scaling containers
ACI sizing
You pick CPU and memory in GB at deployment time. The former ACI GPU offering was retired on July 14, 2025; do not use old GPU examples for a new ACI design. Quotas apply per region and subscription. If you need to scale an ACI workload you deploy more container groups, for example behind Application Gateway or driven by a script, because ACI has no autoscaler.
Container Apps sizing
For ordinary non-GPU Consumption, the sum across containers in one app must match an allowed CPU/memory pair (for example 0.25 vCPU with 0.5 GiB, 0.5 with 1 GiB, 1 with 2 GiB and so on, always 2 GiB of memory per vCPU). Current workload-profile environments support up to 4 vCPU/8 GiB for ordinary Consumption, while Consumption-only environments are limited to 2 vCPU/4 GiB. Other profiles, including GPU and Flex, use different tables; do not apply the ordinary 2-GiB-per-vCPU rule to every profile.
Container Apps scaling
Scaling is horizontal: replicas are added or removed. You set minReplicas and maxReplicas and one or more scale rules.
| Rule type | Scales on | Example |
|---|---|---|
| HTTP | Concurrent requests per replica | Add a replica for every 50 concurrent requests |
| TCP | Concurrent connections | Non-HTTP service |
| CPU / memory | Utilization of the replica | Heavy computation |
| Custom (KEDA) | Queue length, Event Hubs lag, Kafka and others | Service Bus queue worker |
Important behaviors:
- On a compatible Consumption profile,
minReplicas = 0and a suitable trigger allow scale to zero, avoiding app replica usage charges while at zero; registry, Service Bus, logs, networking and applicable management fees remain. The first request may wait for a cold start. SetminReplicas = 1for latency-sensitive apps. minReplicasandmaxReplicasapply per revision. Multiple active revisions can increase the app's total replica count, and maintenance can temporarily prewarm extra replicas above the usual limit. Treat a scale result as a desired target, not an immediate observed count.- When several rules exist, the highest replica count computed by any rule is used.
- Changing scale rules creates a new revision.
- Scale to zero requires that rules can wake the app: HTTP and event rules do; CPU and memory rules cannot scale from zero because there is no running replica to measure.
Choosing the right service
| Requirement | Best fit |
|---|---|
| Run a single container quickly, one-off task or simple test | ACI |
| Microservices with autoscaling, revisions, scale to zero | Container Apps |
| Full Kubernetes control (custom operators, node pools) | AKS (beyond AZ-104 depth) |
| Web app with PaaS features and slots, container optional | App Service |
Worked example: picking the service and the settings
Scenario. Northwind Traders has an order-processing worker packaged as an image in northwindacr.azurecr.io. It reads messages from a Service Bus queue. At night the queue is empty; during sales events it can contain 20,000 messages. The team wants minimal cost at idle, no cluster to manage, and the registry must be reachable only from the company virtual network.
Step 1 – Registry. Private-only access requires a private endpoint, so the registry must be Premium. Disable public network access, create the private endpoint in a separate, non-delegated subnet and link the workload VNet to the private DNS zone for privatelink.azurecr.io.
Step 2 – Compute service. The worker must scale on queue length and avoid idle app-replica usage charges. ACI cannot scale automatically; AKS adds operational burden. Container Apps supports KEDA queue-based scaling and scale to zero.
Step 3 – Settings. Create an environment integrated with the virtual network. Use the Consumption profile and create the app without ingress (a worker needs none), minReplicas = 0, maxReplicas = 30, and a custom scale rule of type azure-servicebus with messageCount = 100 (one replica per 100 pending messages). Use the registry-mode-appropriate read role on its image-pull identity, and configure the Service Bus scaler and worker with identity authentication and Azure Service Bus Data Receiver. With 20,000 messages and a threshold of 100 the nominal target is 200, but maxReplicas = 30 limits this revision's ordinary scaling target. Provision queue permissions, private DNS and outbound connectivity separately.
Step 4 – Why the alternatives are weaker. An ACI group would run constantly or require external automation to start and stop. A Basic or Standard registry could not use a private endpoint. An HTTP scale rule would never fire because the worker receives no HTTP traffic.
Worked example: a nightly report that keeps restarting
Scenario. A report generator container created in ACI finishes in two minutes, yet the group shows as running all day and the bill is higher than expected.
Reasoning. The container exits successfully, but the default restart policy is Always, so Azure restarts it each time. The fix is to set the restart policy to Never (or OnFailure if retries on error are desired). Recreate the group with the new policy because the restart policy cannot be edited on a running group without redeploying. After the change, the group enters Terminated after completion and compute billing stops.
Why other answers fail. Increasing memory does not change restart behavior. Moving to a different region is irrelevant. Container Apps jobs would also work, but the question asks about fixing the existing ACI group.
Pitfalls and exam tips
- Premium for private endpoints and geo-replication. Memorize it.
- Admin account is not the answer for production authentication; choose managed identity plus the registry-mode-appropriate read role.
- ACI restart policy defaults to Always. Run-once tasks need
NeverorOnFailure. - ACI has no autoscale. If a scenario demands scaling rules, it is not ACI.
- Container Apps ≠ AKS. You never manage nodes or the Kubernetes API in Container Apps.
- Scale-to-zero needs
minReplicas = 0and an event or HTTP rule; CPU rules cannot wake a zero-replica app. - New revision on scale or image change. Multiple revision mode is the tool for canary traffic splits.
- Check ACR role mode. AcrPull works in RBAC-only mode; ABAC mode requires Container Registry Repository Reader. Subscription Contributor is excessive and does not replace data-plane permissions in ABAC mode.
- Resource limits vs. requests. A container group's billed size is based on requests; a limit above the request only allows bursting.
Exam tip: Read the verbs. "Run once and stop" points to ACI with
Never. "Respond to queue depth" points to Container Apps with a KEDA rule. "Replicate across regions" points to Premium ACR.
Mini case study: Adventure Works image platform
Adventure Works has three teams building containerized services. Requirements:
- All images must be stored privately, available in West Europe and East US with low latency, and accessible only over private networking.
- An internal marketing preview container is demo-only and runs for one afternoon each quarter.
- The checkout API must absorb traffic spikes, stay available with at least two replicas during business hours, and expose HTTPS publicly.
- Developers must not use shared passwords.
Solution.
- Create one Premium registry in West Europe, add a geo-replication to East US, disable public access and add private endpoints in each region's hub network. Premium is the only tier offering both features.
- Run the internal marketing preview in ACI in a dedicated ACI-delegated subnet, with a user-assigned identity permitted to pull through the registry’s private endpoint in a different subnet. Publish an internal DNS record for the group’s private IP; VNet-deployed groups do not support public IP/DNS labels. Configure the delegated subnet’s NAT Gateway for required outbound connectivity. Use
OnFailureorAlwayswhile serving and delete the group afterwards. A public audience would require a separate public ingress design, such as Application Gateway. - Deploy the checkout API as a Container App with external ingress,
minReplicas = 2,maxReplicas = 20and an HTTP scale rule at 100 concurrent requests per replica. Keeping two replicas warm reduces cold-start risk; it does not alone guarantee zone resilience. Configure supported zone redundancy separately. The HTTP rule handles spikes. - For repository-level isolation, enable ABAC permissions and assign developers Container Registry Repository Writer at registry scope with a condition for their repository. Add Catalog Lister only if they need to enumerate repositories. Workloads use managed identities with Container Registry Repository Reader and matching repository conditions. In RBAC-only mode use AcrPush/AcrPull at registry scope instead. The admin account stays disabled.
Commentary. Each decision matches one signal in the requirement. The tempting mistake is to use ACI for the checkout API because it is simpler; it lacks autoscaling and ingress features required here.
Key terms
- Azure Container Registry (ACR): managed private registry for images.
- Image tag / repository: name and version of an image inside a registry.
- AcrPull / AcrPush: pull/push roles for RBAC-only registries; ABAC registries use repository roles instead.
- Geo-replication: Premium feature that replicates a registry across regions.
- Container group: set of containers in ACI sharing host, network and volumes.
- Restart policy: Always, OnFailure or Never; controls ACI restarts.
- Container Apps environment: boundary shared by container apps and jobs.
- Revision: immutable version snapshot of a container app.
- Replica: a running instance of a revision.
- KEDA: event-driven autoscaler used by Container Apps.
- Scale to zero: running no replicas when idle (
minReplicas = 0). - Workload profile: compute configuration such as Consumption or Dedicated; Flexible is a preview option with separate limits.
Summary checklist
- I can choose Basic, Standard or Premium ACR from requirements (private endpoints and geo-replication need Premium).
- I can push, pull, build (
az acr build) and import images, and authenticate with Entra ID or managed identity. - I can create an ACI container group, set CPU, memory, restart policy, environment variables and volumes.
- I know ACI has no autoscaling and when to prefer Container Apps.
- I can create a Container Apps environment and app with ingress, secrets and revisions.
- I can configure min and max replicas and HTTP, CPU, memory or KEDA scale rules, and explain scale to zero.
- I can pick between ACI, Container Apps and App Service for a scenario.
Continue learning
Before granting registry permissions, review Azure RBAC roles and effective access. For private image pulls, connect the identity design with Azure virtual network configuration. Compare a containerized web workload with Azure App Service plans, scaling and slots when choosing its hosting service.
Official sources
- AZ-104 study guide: https://learn.microsoft.com/en-us/credentials/certifications/resources/study-guides/az-104 (opens in a new tab)
- Azure Container Registry SKUs: https://learn.microsoft.com/en-us/azure/container-registry/container-registry-skus (opens in a new tab)
- Introduction to container groups (ACI): https://learn.microsoft.com/en-us/azure/container-instances/container-instances-container-groups (opens in a new tab)
- ACI YAML reference: https://learn.microsoft.com/en-us/azure/container-instances/container-instances-reference-yaml (opens in a new tab)
- Scaling in Azure Container Apps: https://learn.microsoft.com/en-us/azure/container-apps/scale-app (opens in a new tab)
- Workload profiles in Azure Container Apps: https://learn.microsoft.com/en-us/azure/container-apps/workload-profiles-overview (opens in a new tab)
- Microsoft documentation: https://learn.microsoft.com/en-us/azure/container-registry/container-registry-rbac-abac-repository-permissions (opens in a new tab)
- Microsoft documentation: https://learn.microsoft.com/en-us/cli/azure/acr (opens in a new tab)
- Microsoft documentation: https://learn.microsoft.com/en-us/azure/container-registry/container-registry-content-trust (opens in a new tab)
- Microsoft documentation: https://learn.microsoft.com/en-us/azure/container-instances/using-azure-container-registry-mi (opens in a new tab)
- Microsoft documentation: https://learn.microsoft.com/en-us/azure/container-instances/container-instances-resource-and-quota-limits (opens in a new tab)
- Microsoft documentation: https://learn.microsoft.com/en-us/azure/container-apps/managed-identity-image-pull (opens in a new tab)
- Microsoft documentation: https://learn.microsoft.com/en-us/azure/container-apps/billing (opens in a new tab)
- Microsoft documentation: https://learn.microsoft.com/en-us/azure/container-apps/containers (opens in a new tab)
- Microsoft documentation: https://learn.microsoft.com/en-us/azure/container-apps/ingress-overview (opens in a new tab)
- Microsoft documentation: https://learn.microsoft.com/en-us/azure/container-apps/log-options (opens in a new tab)
- Deploy ACI into a virtual network: https://learn.microsoft.com/en-us/azure/container-instances/container-instances-vnet (opens in a new tab)
