A Simple Guide to Deploying a Dockerized Python app to Azure | by Bjørnar Kjenaas Mælum | Towards Data Science

So you are telling me you have built an app and now you want to deploy it for everyone to see? Look no further. Here is how to deploy it on Azure using Docker, Azure Container Registry and Azure Container Instances.
This guide uses a FastAPI app as the example app and assumes you are familiar with the basics of using the terminal, building a Python application and basic Docker commands. If you have an app of your own that you want to deploy to Azure the only thing you need is to Dockerize the app using a suitable Dockerfile that matches your app.
What will you have achieved after finishing this guide? Well, you’ll have a deployed version of your app on Azure. Great, right?
First, let’s set up a working FastAPI app we can deploy to Azure. I will be using a simple Hello World example you can find here: https://github.com/bmaelum/fastapi-hello-world
The app contains a main file in the /app folder, this is where the FastAPI code is found.
from fastapi import FastAPI  app = FastAPI(    title="FastAPI - Hello World",        description="This is the Hello World of FastAPI.",    version="1.0.0",)   @app.get("/")def hello_world():        return {"Hello": "World"}
To use app, first fork the repository to create a copy in your own Github account. This is necessary to complete the steps using Github Actions. If you want to use the example code for this guide fork the repo by going to this URL: https://github.com/bmaelum/fastapi-hello-world and click the “Fork” button.
To be able to test the code, clone the repo to your machine:
git clone git@github.com:<your-username>/fastapi-hello-world.git
Then install the requirements found in the requirements.txt file into your environment:
pip install -r requirements.txt
To run the app, simply type:
uvicorn app.main:app
You should see something like this in the terminal:
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Testing the app can be done in the browser or with a tool like Postman. To check out the app in your browser simply go to the URL printed in the terminal, in this case: http://127.0.0.1:8000.
Now, let’s Dockerize the application.
Using Docker to deploy your app is great for many reasons, one of them is that it helps you make sure you have the same environment for your local development as for the deployment on Azure.
Make sure you have a suitable Dockerfile. In the example file the Dockerfile looks like this:
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7 COPY ./app /app COPY requirements.txt .RUN pip --no-cache-dir install -r requirements.txt
To build the Docker image simply run:
docker build -t fastapi-image .
To run the image in a container, simply run:
docker run -p 80:80 -it fastapi-image
To test the app you can use the same address as before, just change the port to 80, like this: http://127.0.0.1:80.
Your app works locally, great! Now it’s time to deploy it to Azure!
Ready to deploy to Azure? Exciting!
Deploying the app to Azure requires us doing a few actions in the Azure portal as well as using Github Actions.
This guide will now be following the official documentation of Microsoft found here: https://docs.microsoft.com/en-us/azure/container-instances/container-instances-github-action
Firstly we need to create a Service Principal, a role, in the desired resource group. If you don’t already have a resource group simply create one by going to Resource groups in the Azure portal.
To create a Service Principal we are using Bash in the Azure Cloud Shell. Open this by clicking on the Cloud Shell icon on the top of the page:
Make sure it is set to Bash in the top left of the Cloud Shell:
Then, create a Service Principal for the Resource Group in Azure by using the following command and give the role a name and the scope is the Resource ID for your Resource Group.
Get the Resource Group ID:
groupId=$(az group show \  --name <resource-group-name> \  --query id --output tsv)
Create the role:
az ad sp create-for-rbac \  --name githubactions \  --scope $groupId \  --role Contributor \  --sdk-auth
This will give you a JSON in this format:
{  "clientId": "",  "clientSecret": "",  "subscriptionId": "",  "tenantId": "",  "activeDirectoryEndpointUrl": "https://login.microsoftonline.com",  "resourceManagerEndpointUrl": "https://management.azure.com/",  "activeDirectoryGraphResourceId": "https://graph.windows.net/",  "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",  "galleryEndpointUrl": "https://gallery.azure.com/",  "managementEndpointUrl": "https://management.core.windows.net/"}
Make sure to save this as it will be used to authenticate when using Github Actions.
To manage a Docker container and images you need to create a Container Registry within Azure.
Search for “Container registries” and choose “Create”. Choose your resource group, a name for the instance and a location. For SKU you can choose the Basic option.
Great, let’s get going with the setup of Github Actions.
Remember the JSON you collected in the previous step? Now it’s time to use it.
Go to Github and the repository containing your app. Then go to Settings -> Secrets and add the following credentials(official docs):
AZURE_CREDENTIALSThe entire JSON output from the service principal creation step
REGISTRY_LOGIN_SERVERThe login server name of your registry (all lowercase). Example: myregistry.azurecr.io
REGISTRY_USERNAMEThe clientId from the JSON output from the service principal creation
REGISTRY_PASSWORDThe clientSecret from the JSON output from the service principal creation
RESOURCE_GROUPThe name of the resource group you used to scope the service principal
Now, let’s setup the workflow using Github Actions. Firstly, go to your repo on Github and click the “Actions” button. From there, choose “Skip this and set up a workflow yourself”.
Replace the existing code in the main.yml file with the following code:
on: [push]name: PythonAppAzureDeploymentjobs:    build-and-deploy:        runs-on: ubuntu-latest        steps:        # checkout the repo        - name: 'Checkout GitHub Action'          uses: actions/checkout@main                  - name: 'Login via Azure CLI'          uses: azure/login@v1          with:            creds: ${{ secrets.AZURE_CREDENTIALS }}                - name: 'Build and push image'          uses: azure/docker-login@v1          with:            login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}            username: ${{ secrets.REGISTRY_USERNAME }}            password: ${{ secrets.REGISTRY_PASSWORD }}        - run: |            docker build . -t ${{ secrets.REGISTRY_LOGIN_SERVER }}/sampleapp:${{ github.sha }}            docker push ${{ secrets.REGISTRY_LOGIN_SERVER }}/sampleapp:${{ github.sha }}                - name: 'Deploy to Azure Container Instances'          uses: 'azure/aci-deploy@v1'          with:            resource-group: ${{ secrets.RESOURCE_GROUP }}            dns-name-label: ${{ secrets.RESOURCE_GROUP }}${{ github.run_number }}            image: ${{ secrets.REGISTRY_LOGIN_SERVER }}/sampleapp:${{ github.sha }}            registry-login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}            registry-username: ${{ secrets.REGISTRY_USERNAME }}            registry-password: ${{ secrets.REGISTRY_PASSWORD }}            name: fastapi-sampleapp            location: 'west europe'
Then, commit the file and because we have specified “on: push” it will run straight away. If it doesn’t make sure the code has been commited and pushed to the repo.
Now, wait for the code to be built and deployed. You can follow the progress by clicking “Actions” and choosing the running pipeline.
If you get the error:
Error: The subscription is not registered to use namespace ‘Microsoft.ContainerInstance’.
Simply do the following in PowerShell:
Register-AzResourceProvider -ProviderNamespace Microsoft.ContainerInstance
Alternatively, in Azure, you can go to “Subscriptions”, choose your subscription, go to Resource Providers, search for “ContainerInstance”, click the desired result and click “Register”.
Your Dockerized app should now be visible when going to the Container Instances in the Azure portal.
To test the app click on the newly deployed Container Instance and go to Properties. Under FQDN there is a URL. Paste the URL in your browser and you should see something like this: