Configure continuous deployment for a Python web app in Azure Container Apps

This article is part of a tutorial about how to containerize and deploy a Python web app to Azure Container Apps. Container Apps enables you to deploy containerized apps without managing complex infrastructure.

In this part of the tutorial, you learn how to configure continuous deployment or delivery (CD) for the container app. CD is part of the DevOps practice of continuous integration / continuous delivery (CI/CD), which is automation of your app development workflow. Specifically, you use GitHub Actions for continuous deployment.

The service diagram shown below highlights the components covered in this article: configuration of CI/CD.


Command lines in this tutorial are shown in the Bash shell, on multiple lines for clarity. For other shell types, change the line continuation characters as appropriate. For example, for PowerShell, use back tick (“`”). Or, remove the continuation characters and enter the command on one line.


To set up continuous deployment, you’ll need:

  • The resources and their configuration created in the [previous article][./] of this tutorial series, which includes an Azure Container Registry and a container app in Azure Container Apps.

  • A GitHub account where you forked the sample code (Django or Flask) and you can connect to from Azure Container Apps. (If you downloaded the sample code instead of forking, make sure you push your local repo to your GitHub account.)

  • Optionally, Git installed in your development environment to make code changes and push to your repo in GitHub. Alternatively, you can make the changes directly in GitHub.

Configure CD for a container

In a previous article of this tutorial, you created and configured a container app in Azure Container Apps. Part of the configuration was pulling a Docker image from an Azure Container Registry. The container image is pulled from the registry when creating a container revision, such as when you first set up the container app.

In the steps below, you’ll set up continuous deployment, which means a new Docker image and container revision are created based on a trigger. The trigger in this tutorial is any change to the main branch of your repository, such as with a pull request (PR). When triggered, the workflow creates a new Docker image, pushes it to the Azure Container Registry, and updates the container app to a new revision using the new image.

Step 1. In the Azure portal, go to the Container App you want to configure continuous deployment for and select the Continuous deployment resource.

Step 2. Authorize Azure Container Apps to access your GitHub account.

  • Select Sign in with GitHub.
  • In the authorization pop up, select AuthorizeAppService.

Container App access to the GitHub accont can be revoked by going to the your account’s security section and revoking access.

Step 3. After sign-in with GitHub, configure the continuous deployment details.

  • Organization → Use your GitHub user name.
  • Repository → Select the fork of the sample app. (If you originally downloaded the sample code to your developer environment, push the repo to GitHub.)
  • Branch → Select main.
  • Repository source → Select Azure Container Registry.
  • Registry → Select the Azure Container Registry you created earlier in the tutorial.
  • Image → Select the Docker image name. If you are following the tutorial, it’s “python-container-app”.
  • Service principal → Leave Create new and let the creation process create a new service principal.

Select Start continuous deployment to finish the configuration.

Step 4. Review the continuous deployment information.

After the continuous deployment is configured, you can find a link to the GitHub Actions workflow file created. Azure Container Apps checked the file in to your repo.

In the configuration of continuous deployment, a service principal is used to enable GitHub Actions to access and modify Azure resources. Access to resources is restricted by the roles assigned to the service principal. The service principal was assigned the built-in Contributor role on the resource group containing the container app.

If you followed the steps for the portal, the service principal was automatically created for you. If you followed the steps for the Azure CLI, you explicitly created the service principal first before configuring continuous deployment.

Redeploy web app with GitHub Actions

In this section, you’ll make a change to your forked copy of the sample repository and confirm that the change is automatically deployed to the web site.

If you haven’t already, make a fork of the sample repository (Django or Flask). You can make your code change directly in GitHub or in your development environment from a command line with Git.

Step 1. Go to your fork of the sample repository and start in the main branch.

Step 2. Make a change.

  • Go to the /templates/base.html file.
  • Select Edit and change the phrase “Azure Restaurant Review” to “Azure Restaurant Review – Redeployed”.

Step 3. Commit the change directly to the main branch.

  • On the bottom of the page you editing, select the Commit button.
  • The commit kicks off the GitHub Actions workflow.


We showed making a change directly in the main branch. In typical software workflows, you’ll make a change in a branch other than main and then create a pull request (PR) to merge those change into main. PRs also kick off the workflow.

About GitHub Actions

Viewing workflow history

Step 1. On GitHub, go to your fork of the sample repository and open the Actions tab.

Workflow secrets

In the .github/workflows/<workflow-name>.yml workflow file that was added to the repo, you’ll see placeholders for credentials that are needed for the build and container app update jobs of the workflow. The credential information is stored encrypted in the repository Settings under Security/Actions.

If credential information changes, you can update it here. For example, if the Azure Container Registry passwords are regenerated, you’ll need to update the REGISTRY_PASSWORD value. For more information, see Encrypted secrets in the GitHub documentation.

OAuth authorized apps

When you set up continuous deployment, you authorize Azure Container Apps as an authorized OAuth App for your GitHub account. Container Apps uses the authorized access to create a GitHub Actions YML file in .github/workflows/<workflow-name>.yml. You can see your authorized apps and revoke permissions under Integrations/Applications of your account.

Troubleshooting tips

Errors setting up a service principal with the Azure CLI az ad sp create-for-rba command.

  • You receive an error containing “InvalidSchema: No connection adapters were found”.

    • Check the shell you’re running in. If using Bash shell, set the MSYS_NO_PATHCONV variables as follows export MSYS_NO_PATHCONV=1. For more information, see the GitHub issue Unable to create service principal with Azure CLI from git bash shell, no connection adapters were found..
  • Check the shell you’re running in. If using Bash shell, set the MSYS_NO_PATHCONV variables as follows
  • You receive an error containing “More than one application have the same display name”.

    • This error indicates the name is already taken for the service principal. Choose another name or leave off the --nameargument and a GUID will be automatically generated as a display name.
  • This error indicates the name is already taken for the service principal. Choose another name or leave off the

GitHub Actions workflow failed.

  • To check a workflow’s status, go to the Actions tab of the repo.
  • If there’s a failed workflow, drill into its workflow file. There should be two jobs “build” and “deploy”. For a failed job, look at the output of the job’s tasks to look for problems.
  • If you see an error message with “TLS handshake timeout”, run the workflow manually by selecting Trigger auto deployment under the Actions tab of the repo to see if the timeout is a temporary issue.
  • If you set up continuous deployment for the container app as shown in this tutorial, the workflow file (.github/workflows/<workflow-name>.yml) is created automatically for you. You shouldn’t need to modify this file for this tutorial. If you did, revert your changes and try the workflow.

Website doesn’t show changes you merged in the main branch.

  • In GitHub: check that the GitHub Actions workflow ran and that you checked the change into the branch that triggers the workflow.
  • In Azure portal: check the Azure Container Registry to see if a new Docker image was created with a timestamp after your change to the branch.
  • In Azure portal: check the logs of the container app. If there’s a programming error, you’ll see it here.
    • Go to the Container App | Revision Management | <active container> | Revision details | Console logs
    • Choose the order of the columns to show “Time Generated”, “Stream_s”, and “Log_s”. Sort the logs by most-recent first and look for Python stderr and stdout messages in the “Stream_s” column. Python ‘print’ output will be stdout messages.
  • With the Azure CLI, use the az containerapp logs show command.

What happens when I disconnect continuous deployment?

  • Stopping continuous deployment means disconnecting your container app from your repo. To disconnect:

    • In Azure portal, go the container app, select the Continuous deployment resource, select Disconnect.
    • With the Azure CLI, use the az container app github-action remove command.
  • After disconnecting, in your GitHub repo:

    • The .github/workflows/<workflow-name>.yml file is removed from your repo.
    • Secret keys aren’t removed.
    • Azure Container Apps remains as an authorized OAuth App for your GitHub account.
  • After disconnecting, in Azure:

    • The container is left with last deployed container. You can reconnect the container app with the Azure Container Registry, so that new container revisions pick up the latest image.
    • Service principals created and used for continuous deployment aren’t deleted.

Next steps

If you’re done with the tutorial and don’t want to incur extra costs, remove the resources used. Removing a resource group removes all resources in the group and is the fastest way to remove resources. For an example of how to remove resource groups, see Containerize tutorial cleanup.

If you plan on building on this tutorial, here are some next steps you can take.


Submit and view feedback for

You are watching: Configure CI/CD for a Python web app in Azure Container Apps. Info created by Bút Chì Xanh selection and synthesis along with other related topics.