The world’s leading publication for data science, AI, and ML professionals.

Deploy FastAPI on Azure with Github Actions

Automate your deployment workflow with Github Actions

Github Actions

Github Actions is a new workflow automation tool for building, testing, and deploying your code directly from Github.

If you’re already using Github for your code repository, there’s no need to integrate a third-party tool to automate common developer workflows.

Simply place a Github Actions .yml file in your repository, designed to run in response to specific events. (push, pull requests, etc)

Workflow diagram

Today we’re going to go through an example workflow using Python to build a barebones API, with FastAPI as the framework of choice.

Github Actions workflow diagram. Image by author.
Github Actions workflow diagram. Image by author.

We will build and push a container image to Azure Container Registry, and pull the image into an Azure Web App for deployment.

Note that this article assumes prior knowledge of the technologies listed below.

The shell command examples given are on macOS. But you should be able to find equivalent commands if you’re developing on Windows.

The full list of packages and technologies we’ll be utilizing include:

  • VS Code – as the IDE of choice.
  • pipenv – to handle package dependencies, create virtual environments, and load environment variables.
  • FastAPI— Python API development framework.
  • Uvicorn – ASGI server for FastAPI app.
  • Docker Desktop— build and run Docker container images on our local machine.
  • Azure Container Registry – repository for storing our container image in Azure cloud.
  • Azure App Service – PaaS service to host our Fastapi app server.
  • Github Actions – automate continuous deployment workflow of FastAPI app.

Go ahead and download VS Code and Docker Desktop from the links above, as we will be needing those two programs throughout this guide.

Project setup on local machine

Create your project folder

In your terminal, navigate to a folder where you want to create your project, and run the following commands.

mkdir fastapi-cd
cd fastapi-cd
code .
Create project folder. Gif by author.
Create project folder. Gif by author.

VS Code should start up with the project folder you created.

Install pipenv

pipenv is a versatile package that removes the need for a requirements.txt file usually found in Python apps.

Hit Ctrl + ~ to open a VS Code terminal, and enter the commands:

sudo -H pip install -U pipenv
pipenv install fastapi uvicorn
pipenv install packages. Gif by author.
pipenv install packages. Gif by author.

pipenv will proceed to install the libraries in a virtual environment and manage the dependencies for you in a Pipfile.

Pipfile package management. Image by author.
Pipfile package management. Image by author.

Because pipenv creates a virtual environment for your project, you don’t need to use the regular venv / virtualenv command either.

Simply use pipenv shell to activate the virtual environment.

pipenv shell
uvicorn --version
exit
uvicorn --version

Use the exit command to exit the virtual environment.

Note that uvicorn is no longer accessible outside of the environment. It was only installed in the virtual environment accessible using pipenv shell.

Activate virtual environment with pipenv shell. Gif by author.
Activate virtual environment with pipenv shell. Gif by author.

Create project files

Create the following files in the project directory.

touch main.py .env .gitignore .dockerignore Dockerfile

In the .gitignore and .dockerignore files, list .env as a file to ignore in your project folder.

Github

Create a bare Github repo without any files and copy the repo URL.

Start tracking the changes from your local repo. In the VS Code terminal, run:

git init
git add .
git commit -m "first commit"
git remote add origin <github repo url>
git push -u origin main

Docker

Head over to Docker Desktop and install the program.

This allows you to run Docker commands on your local machine.

Docker Desktop for Mac and Windows | Docker

Code

We’re finally done with the setup. Time to code. Head back to VS Code. In .env, set PORT=8000.

In main.py, enter the following code:

The default address route will now return you a success message.

Run pipenv run python main.py in the VS code terminal to start the uvicorn server:

Then go to [http://localhost:8000/docs](http://localhost:8000/docs) to see if FastAPI is running.

FastAPI swagger docs. Image by author.
FastAPI swagger docs. Image by author.

Note that pipenv loads your environment variables, PORT=8000, for you, before running main.py.

Build and Run Container Image

Instead of deploying our app as a package, let’s build our app as a Docker image, so that the build process is outlined in a Dockerfile.

Dockerfile makes the build process seamless and reproducible.

In the Dockerfile, write the following:

Build your container and check that the image has been created with the docker images command.

docker build . -t fastapi-cd:1.0
docker images

Run your container with the image tag you specified earlier, on port 8000.

docker run -p 8000:8000 -t fastapi-cd:1.0

Check your containerized application by going to [http://localhost:8000/docs](http://localhost:8000/docs).

You should see the same FastAPI application running.

Congratulations! You just built a simple FastAPI application, and containerized it using a Docker container on your local machine.

Infrastructure setup

Azure Container Registry

Time to deploy our application in Azure. First off, create an Azure Container Registry.

Create Azure Container Registry. Image by author.
Create Azure Container Registry. Image by author.

Enable the admin user option in the Access keys pane.

Enable admin user. Image by author.
Enable admin user. Image by author.

Going back to your VS Code terminal, log in to Azure with your account.

az login
az acr login --name fastapicd

Build and push your Docker image to the registry server.

docker build . -t fastapicd.azurecr.io/fastapi-cd:1.0
docker images
docker push fastapicd.azurecr.io/fastapi-cd:1.0
Push container image to Azure Container Registry server. Gif by author.
Push container image to Azure Container Registry server. Gif by author.

Check that your Docker image has been successfully pushed to a repo in the registry.

Verify container image in Azure Container Registry repo. Image by author.
Verify container image in Azure Container Registry repo. Image by author.

Azure App Service

Next, create an App Service resource.

Create App Service. Image by author.
Create App Service. Image by author.

For the App Service Plan, change the size to Standard S1 SKU under the Production Workloads tab.

Standard S1 App Service Plan. Image by author.
Standard S1 App Service Plan. Image by author.

On the Docker configuration tab, make sure the container image you pushed earlier is selected.

Configure App Service to use container image. Image by author.
Configure App Service to use container image. Image by author.

Once resource deployment is complete, check that your web app is running by going to [https://<your-webapp-name>.azurewebsites.net/docs](https://<your-webapp-name>.azurewebsites.net/docs).

You should see the FastAPI swagger docs page render.

Github Actions

Now we’re ready to create our Github Actions .yml file that will automate deployment of our FastAPI application.

In VS Code, create a .github/workflows directory and a prod.workflow.yml file within.

mkdir .github
cd .github
mkdir workflows
cd ..
touch .github/workflows/prod.workflow.yml

Build your prod.workflow.yml file like below:

Now, whenever we do a git push to the main branch, Github Actions will run a deployment job that consists of the 5 steps above, each with its own name.

Push this new file to Github using the git commands:

git add .
git commit -m "github actions deployment workflow"
git push

Service Principal

To automate our deployment workflow with Github Actions, we need to give the actions runner a service principal to authenticate to Azure, and perform the app deployment.

In VS Code terminal, run:

az ad sp create-for-rbac --name "github-actions" --role contributor --scopes /subscriptions/<GUID>/resourceGroups/fastapi-cd --sdk-auth

You can get the subscription GUID from the subscription you used to create the resource group.

You will get a response like below:

Copy the response and save it. You won’t be able to see it again.

Head over to Github settings, and create 3 Github Secrets:

  • AZURE CREDENTIALS: Entire JSON response from above.
  • REGISTRY_USERNAME: clientId value from JSON response.
  • REGISTRY_PASSWORD: clientSecret value from JSON response.
Create Github secret. Image by author.
Create Github secret. Image by author.

Configure App Service to use Github Actions for continuous deployment

In the Deployment Center pane of the App Service, link your Github repo main branch, and configure deployment to use Github Actions.

Configure app to continuously deploy with Github Actions. Image by author.
Configure app to continuously deploy with Github Actions. Image by author.

Create staging deployment slot

The current app is running in a production slot. To guarantee higher-quality deployments, we will create a staging slot.

Create staging deployment slot. Image by author.
Create staging deployment slot. Image by author.

Slots are useful for multiple reasons:

  • Changes can be released to a smaller % of users in a staging slot, to validate new releases before swapping the staging slot with production.
  • Staging slot app instances are warmed up before being swapped into production, guaranteeing that the app is responsive to requests.
  • If something goes wrong with the new release, swaps can be performed again to roll back the changes.

Check that the staging app is running like the production app by going to [https://<your-webapp-name>-staging.azurewebsites.net/docs](https://<your-webapp-name>-staging.azurewebsites.net/docs).

Configure the same deployment center settings for the staging slot as you did for production.

Push new releases to the staging slot.

In your main.py file, make a change to the return message.

return {"data": "Application ran successfully - FastAPI release v2.0"}

Do a git push to main branch to trigger the Github Actions workflow.

git add .
git commit -m "FastAPI v2.0 release"
git push

Github Actions will build and deploy the new version of your application to the staging slot automatically.

Github Actions deployment job. Image by author.
Github Actions deployment job. Image by author.

Check the new version of your application by going to [https://<your-webapp-name>-staging.azurewebsites.net/docs](https://<your-webapp-name>-staging.azurewebsites.net/docs).

Send a request to the default route to check the response. You should see v2.0 in the return message.

Verify new app release to staging slot. Image by author.
Verify new app release to staging slot. Image by author.

When you’re comfortable swapping the staging app over to production, simply click on Swap in the Deployment Slots pane of the App Service.

Swap staging app into production. Image by author.
Swap staging app into production. Image by author.

Do the same verification of the new app version as above by going to the production URL [https://<your-webapp-name>.azurewebsites.net/docs](https://<your-webapp-name>.azurewebsites.net/docs).

Conclusion

Velocity matters when you’re developing software applications.

As developers, there’s a lot of things we have to keep up with – provisioning infrastructure, spinning up new environments, application testing, etc.

If we automate the boring stuff, we can focus our time on the most key tasks – building new features.

In this article, we automated the release and deploy phase of the DevOps lifecycle with Github Actions. This gives us confidence to release often into production without deployment failures.

DevOps lifecycle.
DevOps lifecycle.

Resources

All code written in this article can be found at the Github repo:

GitHub – natworkeffects/fastapi-cd

I would like to give a big shoutout to all the extensive documentation and YouTube videos that helped to complete this article:


Related Articles