Skip to content

Container Deploy from Azure Container Registry

Use container deployment when you want App Service to run a custom Linux container image instead of a built-in runtime stack. The deployment unit becomes the container image, so your release process should manage registry access, image versioning, and health validation.

Main Content

Container Deployment Flow

flowchart TD
    A[Build container image] --> B[Push image to Azure Container Registry]
    B --> C[Create or update App Service with image reference]
    C --> D[Grant AcrPull access or registry credentials]
    D --> E[App Service pulls image]
    E --> F[Container starts and responds on app port]
    F --> G{Continuous deployment enabled?}
    G -- Yes --> H[Registry push triggers webhook-based redeploy]
    G -- No --> I[Manual image update or restart]

Prepare Azure Container Registry

az acr create \
  --resource-group $RG \
  --name $ACR_NAME \
  --sku Basic \
  --admin-enabled false \
  --output json

az acr build \
  --registry $ACR_NAME \
  --image sample-app:v1 \
  .
Command/Parameter Purpose
az acr create Creates an Azure Container Registry.
--resource-group $RG Places the registry in the selected resource group.
--name $ACR_NAME Sets the registry name.
--sku Basic Chooses the Basic pricing tier for the registry.
--admin-enabled false Disables admin username/password access in favor of stronger identity-based access.
--output json Returns structured output after registry creation.
az acr build Builds the container image in ACR.
--registry $ACR_NAME Chooses which registry performs the cloud build.
--image sample-app:v1 Tags the built image as sample-app:v1.
. Uses the current directory as the Docker build context.

Create a Web App with a Container Image

az webapp create \
  --resource-group $RG \
  --plan $PLAN_NAME \
  --name $APP_NAME \
  --deployment-container-image-name "$ACR_NAME.azurecr.io/sample-app:v1" \
  --output json
Command/Parameter Purpose
az webapp create Creates the App Service web app.
--resource-group $RG Places the app in the selected resource group.
--plan $PLAN_NAME Places the app in the specified App Service Plan.
--name $APP_NAME Sets the web app name.
--deployment-container-image-name "$ACR_NAME.azurecr.io/sample-app:v1" Configures the app to pull and run the specified container image.
--output json Returns structured output after app creation.

Portal view: Create Web App Container tab

Azure Portal Create Web App wizard with the Container tab selected and Basics, Database, Container (selected), Networking, Monitor + secure, Tags, and Review + create tab strip visible. Header text reads "Select your preferred source for container images. You can change these settings and other dependencies after creating the app. Learn more". A Sidecar support toggle is ON with the label "Enhanced configuration with sidecar support on Learn More". The Image Source field shows three radio options: Quickstart (selected), Azure Container Registry, and Other container registries; the Name field is set to main. A Quickstart options section follows with Sample dropdown set to NGINX and the helper text "NGINX web server default site.", a disabled Image and tag field showing mcr.microsoft.com/appsvc/staticsite:latest, and Port set to 80. Bottom toolbar buttons are Review + create (primary), < Previous, and Next : Networking >.

This is the click-driven equivalent of the az webapp create --deployment-container-image-name command shown above. The Sidecar support toggle defaults to ON in new app creation, which matches the Multi-Container Note guidance below - sidecar containers are the long-term direction and Docker Compose is on its way out. The default Quickstart image source with the mcr.microsoft.com/appsvc/staticsite:latest placeholder is intentional: it lets you create the app shell before the real ACR image is ready, but production setups should switch to Azure Container Registry immediately so the Configure Managed Identity Pull from ACR step below can grant AcrPull instead of leaving the wizard on the public quickstart image. The default Port: 80 aligns with the WEBSITES_PORT guidance in Runtime Settings to Remember - if your container listens on a different port, set it here or via app settings before the first deployment, not after.

Configure Managed Identity Pull from ACR

PRINCIPAL_ID=$(az webapp identity assign \
  --resource-group $RG \
  --name $APP_NAME \
  --query principalId \
  --output tsv)

ACR_RESOURCE_ID=$(az acr show \
  --resource-group $RG \
  --name $ACR_NAME \
  --query id \
  --output tsv)

az role assignment create \
  --assignee $PRINCIPAL_ID \
  --scope $ACR_RESOURCE_ID \
  --role AcrPull \
  --output json

az webapp config set \
  --resource-group $RG \
  --name $APP_NAME \
  --generic-configurations '{"acrUseManagedIdentityCreds": true}' \
  --output json
Command/Parameter Purpose
PRINCIPAL_ID=$(...) Captures the web app managed identity principal ID into a shell variable.
az webapp identity assign Enables a managed identity on the web app.
--resource-group $RG Targets the resource group that contains the app.
--name $APP_NAME Selects the web app that needs an identity.
--query principalId Returns only the managed identity principal ID.
--output tsv Formats the query result for shell variable assignment.
ACR_RESOURCE_ID=$(...) Captures the ACR resource ID into a shell variable.
az acr show Retrieves metadata about the registry.
--resource-group $RG Targets the resource group that contains the registry.
--name $ACR_NAME Selects the registry to inspect.
--query id Returns only the registry resource ID.
--output tsv Formats the query result for shell variable assignment.
az role assignment create Creates an RBAC role assignment.
--assignee $PRINCIPAL_ID Grants the role to the web app managed identity.
--scope $ACR_RESOURCE_ID Applies the role assignment at the registry scope.
--role AcrPull Grants image pull permissions on the registry.
--output json Returns structured output for the role assignment and final configuration commands.
az webapp config set Updates general web app configuration values.
--resource-group $RG Targets the resource group that contains the app.
--name $APP_NAME Selects the web app whose container pull settings are being updated.
--generic-configurations '{"acrUseManagedIdentityCreds": true}' Tells App Service to use managed identity credentials for ACR pulls.

Prefer managed identity

Managed identity is the preferred production approach because it removes long-lived registry passwords from the deployment path.

Enable Continuous Deployment from ACR

CI_CD_URL=$(az webapp deployment container config \
  --resource-group $RG \
  --name $APP_NAME \
  --enable-cd true \
  --query CI_CD_URL \
  --output tsv)

az acr webhook create \
  --resource-group $RG \
  --registry $ACR_NAME \
  --name appservice-cd \
  --actions push \
  --uri $CI_CD_URL \
  --scope 'sample-app:v1' \
  --output json
Command/Parameter Purpose
CI_CD_URL=$(...) Captures the App Service webhook URL into a shell variable.
az webapp deployment container config Reads or updates App Service container deployment settings.
--resource-group $RG Targets the resource group that contains the app.
--name $APP_NAME Selects the web app to configure.
--enable-cd true Enables continuous deployment for container image updates.
--query CI_CD_URL Returns only the webhook URL that App Service exposes.
--output tsv Formats the URL for shell variable assignment.
az acr webhook create Creates a webhook in ACR.
--resource-group $RG Targets the resource group that contains the registry.
--registry $ACR_NAME Selects the registry that will emit webhook events.
--name appservice-cd Names the webhook resource.
--actions push Triggers the webhook when an image is pushed.
--uri $CI_CD_URL Sends webhook events to the App Service continuous deployment endpoint.
--scope 'sample-app:v1' Limits the webhook to pushes for sample-app:v1, so later immutable tags such as v2 require a scope update or a stable deployment tag strategy.
--output json Returns structured webhook creation output.

Webhook dependency

App Service continuous deployment for containers depends on the webhook path remaining valid. Treat webhook configuration as part of the application release infrastructure, not as a one-time portal setting.

Update the Image on an Existing App

az webapp config container set \
  --resource-group $RG \
  --name $APP_NAME \
  --docker-custom-image-name "$ACR_NAME.azurecr.io/sample-app:v2" \
  --docker-registry-server-url "https://$ACR_NAME.azurecr.io" \
  --output json
Command/Parameter Purpose
az webapp config container set Updates container settings for an existing web app.
--resource-group $RG Targets the resource group that contains the app.
--name $APP_NAME Selects the web app to update.
--docker-custom-image-name "$ACR_NAME.azurecr.io/sample-app:v2" Points the app to the newer v2 image tag.
--docker-registry-server-url "https://$ACR_NAME.azurecr.io" Declares the registry endpoint where the image is hosted.
--output json Returns structured output after the configuration update.

Multi-Container Note

App Service supports Docker Compose for multi-container scenarios, but Microsoft Learn currently positions sidecar containers as the long-term direction and notes Docker Compose retirement on March 31, 2027.

az webapp config container set \
  --resource-group $RG \
  --name $APP_NAME \
  --multicontainer-config-file ./docker-compose.yml \
  --output json
Command/Parameter Purpose
az webapp config container set Updates the app to use a multi-container configuration.
--resource-group $RG Targets the resource group that contains the app.
--name $APP_NAME Selects the web app to update.
--multicontainer-config-file ./docker-compose.yml Supplies the Docker Compose file that defines the multi-container app.
--output json Returns structured output after the configuration update.

Plan for sidecar migration

If you are starting a new design, prefer App Service sidecar container patterns over Docker Compose. Use Docker Compose only when you are maintaining an existing multi-container deployment model.

Advanced Topics

Runtime Settings to Remember

  • Set WEBSITES_PORT if the container listens on a port other than 80.
  • Use WEBSITES_ENABLE_APP_SERVICE_STORAGE=true only when the app requires persistent /home storage.
  • For private endpoint registries, route image pulls through virtual network integration where required.

Verification Commands

az webapp config container show \
  --resource-group $RG \
  --name $APP_NAME \
  --output json

az webapp log tail \
  --resource-group $RG \
  --name $APP_NAME
Command/Parameter Purpose
az webapp config container show Displays the current container configuration for the app.
--resource-group $RG Targets the resource group that contains the app.
--name $APP_NAME Selects the web app to inspect.
--output json Returns the container configuration in JSON format.
az webapp log tail Streams live application and container logs.
--resource-group $RG Targets the resource group that contains the app.
--name $APP_NAME Selects the web app whose logs should be tailed.

See Also

Sources