Continuous deployment with custom containers in Azure App Service

In this tutorial, you configure continuous deployment for a custom container image from managed Azure Container Registry repositories or Docker Hub.

1. Go to Deployment Center

In the Azure portal, navigate to the management page for your App Service app.

From the left menu, click Deployment Center > Settings.

2. Choose deployment source

Choose the deployment source depends on your scenario:

  • Container registry sets up CI/CD between your container registry and App Service.
  • The GitHub Actions option is for you if you maintain the source code for your container image in GitHub. Triggered by new commits to your GitHub repository, the deploy action can run docker build and docker push directly to your container registry, then update your App Service app to run the new image. For more information, see How CI/CD works with GitHub Actions.
  • To set up CI/CD with Azure Pipelines, see Deploy an Azure Web App Container from Azure Pipelines.

Note

For a Docker Compose app, select Container Registry.

If you choose GitHub Actions, click Authorize and follow the authorization prompts. If you've already authorized with GitHub before, you can deploy from a different user's repository by clicking Change Account.

Once you authorize your Azure account with GitHub, select the Organization, Repository, and Branch to deploy from.

2. Configure registry settings

3. Configure registry settings

Note

Sidecar containers (preview) will succeed multi-container (Docker Compose) apps in App Service. To get started, see Tutorial: Configure a sidecar container for custom container in Azure App Service (preview).

To deploy a multi-container (Docker Compose) app, select Docker Compose in Container Type.

If you don't see the Container Type dropdown, scroll back up to Source and select Container Registry.

In Registry source, select where your container registry is. If it's neither Azure Container Registry nor Docker Hub, select Private Registry.

Note

If your multi-container (Docker Compose) app uses more than one private image, make sure the private images are in the same private registry and accessible with the same user credentials. If your multi-container app only uses public images, select Docker Hub, even if some images are not in Docker Hub.

Follow the next steps by selecting the tab that matches your choice.

The Registry dropdown displays the registries in the same subscription as your app. Select the registry you want.

Note

Select the Image and Tag to deploy. If you want, type the start up command in Startup File.

Follow the next step depending on the Container Type:

  • For Docker Compose, select the registry for your private images. Click Choose file to upload your Docker Compose file, or just paste the content of your Docker Compose file into Config.
  • For Single Container, select the Image and Tag to deploy. If you want, type the start up command in Startup File.

App Service appends the string in Startup File to the end of the docker run command (as the [COMMAND] [ARG...] segment) when starting your container.

3. Enable CI/CD

4. Enable CI/CD

App Service supports CI/CD integration with Azure Container Registry and Docker Hub. To enable it, select On in Continuous deployment.

Note

If you select GitHub Actions in Source, you don't get this option because CI/CD is handled by GitHub Actions directly. Instead, you see a Workflow Configuration section, where you can click Preview file to inspect the workflow file. Azure commits this file into your selected GitHub source repository to handle build and deploy tasks. For more information, see How CI/CD works with GitHub Actions.

When you enable this option, App Service adds a webhook to your repository in Azure Container Registry or Docker Hub. Your repository posts to this webhook whenever your selected image is updated with docker push. The webhook causes your App Service app to restart and run docker pull to get the updated image.

Note

To ensure the proper functioning of the webhook, it's essential to enable the Basic Auth Publishing Credentials option within your Web App. Failure to do so may result in a 401 unauthorized error for the webhook. To verify whether Basic Auth Publishing Credentials is enabled, follow these steps:

  • Navigate to your Web App's Configuration > General Settings.
  • Look for the Platform Setting section, where you will find the Basic Auth Publishing Credentials option.

For other private registries, your can post to the webhook manually or as a step in a CI/CD pipeline. In Webhook URL, click the Copy button to get the webhook URL.

Note

Support for multi-container (Docker Compose) apps is limited:

  • For Azure Container Registry, App Service creates a webhook in the selected registry with the registry as the scope. A docker push to any repository in the registry (including the ones not referenced by your Docker Compose file) triggers an app restart. You may want to modify the webhook to a narrower scope.
  • Docker Hub doesn't support webhooks at the registry level. You must add the webhooks manually to the images specified in your Docker Compose file.

4. Save your settings

5. Save your settings

Click Save.

How CI/CD works with GitHub Actions

If you choose GitHub Actions in Source (see Choose deployment source), App Service sets up CI/CD in the following ways:

  • Deposits a GitHub Actions workflow file into your GitHub repository to handle build and deploy tasks to App Service.
  • Adds the credentials for your private registry as GitHub secrets. The generated workflow file runs the Azure/docker-login action to sign in with your private registry, then runs docker push to deploy to it.
  • Adds the publishing profile for your app as a GitHub secret. The generated workflow file uses this secret to authenticate with App Service, then runs the Azure/webapps-deploy action to configure the updated image, which triggers an app restart to pull in the updated image.
  • Captures information from the workflow run logs and displays it in the Logs tab in your app's Deployment Center.

You can customize the GitHub Actions build provider in the following ways:

  • Customize the workflow file after it's generated in your GitHub repository. For more information, see Workflow syntax for GitHub Actions. Just make sure that the workflow ends with the Azure/webapps-deploy action to trigger an app restart.
  • If the selected branch is protected, you can still preview the workflow file without saving the configuration, then add it and the required GitHub secrets into your repository manually. This method doesn't give you the log integration with the Azure portal.
  • Instead of a publishing profile, deploy using a service principal in Microsoft Entra ID.

Authenticate with a service principal

This optional configuration replaces the default authentication with publishing profiles in the generated workflow file.

Generate a service principal with the az ad sp create-for-rbac command in the Azure CLI. In the following example, replace <subscription-id>, <group-name>, and <app-name> with your own values. Save the entire JSON output for the next step, including the top-level {}.

az ad sp create-for-rbac --name "myAppDeployAuth" --role contributor \
                            --scopes /subscriptions/<subscription-id>/resourceGroups/<group-name>/providers/Microsoft.Web/sites/<app-name> \
                            --json-auth

Important

For security, grant the minimum required access to the service principal. The scope in the previous example is limited to the specific App Service app and not the entire resource group.

In GitHub, browse to your repository, then select Settings > Secrets > Add a new secret. Paste the entire JSON output from the Azure CLI command into the secret's value field. Give the secret a name like AZURE_CREDENTIALS.

In the workflow file generated by the Deployment Center, revise the azure/webapps-deploy step with code like the following example:

- name: Sign in to Azure 
# Use the GitHub secret you added
- uses: azure/login@v1
    with:
    creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Deploy to Azure Web App
# Remove publish-profile
- uses: azure/webapps-deploy@v2
    with:
    app-name: '<app-name>'
    slot-name: 'production'
    images: '<registry-server>/${{ secrets.AzureAppService_ContainerUsername_... }}/<image>:${{ github.sha }}'
    - name: Sign out of Azure
    run: |
    az logout

Automate with CLI

To configure the container registry and the Docker image, run az webapp config container set.

az webapp config container set --name <app-name> --resource-group <group-name> --docker-custom-image-name '<image>:<tag>' --docker-registry-server-url 'https://<registry-name>.azurecr.io' --docker-registry-server-user '<username>' --docker-registry-server-password '<password>'

To configure a multi-container (Docker Compose) app, prepare a Docker Compose file locally, then run az webapp config container set with the --multicontainer-config-file parameter. If your Docker Compose file contains private images, add --docker-registry-server-* parameters as shown in the previous example.

az webapp config container set --resource-group <group-name> --name <app-name> --multicontainer-config-file <docker-compose-file>

To configure CI/CD from the container registry to your app, run az webapp deployment container config with the --enable-cd parameter. The command outputs the webhook URL, but you must create the webhook in your registry manually in a separate step. The following example enables CI/CD on your app, then uses the webhook URL in the output to create the webhook in Azure Container Registry.

ci_cd_url=$(az webapp deployment container config --name <app-name> --resource-group <group-name> --enable-cd true --query CI_CD_URL --output tsv)

az acr webhook create --name <webhook-name> --registry <registry-name> --resource-group <group-name> --actions push --uri $ci_cd_url --scope '<image>:<tag>'

More resources