DEV Community

Cover image for Dockerizing a FastAPI CRUD App: Automating Builds and Pushes with GitHub Actions
Kene Ojiteli
Kene Ojiteli

Posted on

Dockerizing a FastAPI CRUD App: Automating Builds and Pushes with GitHub Actions

FastAPI is a high-performance Python framework for building APIs, and Docker allows us to containerize applications to make them easier to deploy. In this guide, we'll containerize a FastAPI app with Docker, and automate the build and push of the Image to a private container registry using GitHub actions.

Prerequisites

  • Python and fastAPI dependencies (including pydantic for validation, fastAPI, uvicorn).
  • Docker - to build the fastAPI application into an image and push to a private registry.
  • GitHub and GitHub Actions: for version control and CICD to automate image build and push.
  • Terminal and a code editor / IDE: for code development, image building and CICD.

Steps taken

  • Testing the application locally.
  • Manually build the image.
  • Automate with GitHub Actions.

Testing the application locally

  • Install Python and fastAPI using pip, verify the installation by checking the version
  • Create a main.py, requirements.txt (I did a pip freeze and saved it to the requirements.txt file).
  • The main.py contains the CRUD app built with fastAPI.

crud app

crud app-1

  • I also installed an email-validator, since my validation with pydantic requires validating the email field.

Install email validator

  • I ran the application with uvicorn main:app --reload

run with uvicorn

  • I accessed the application via http://127.0.0.1:8000/users/ or via http://127.0.0.1:8000/docs#/

Access API

Access via swagger UI

Manually build the image

  • I built the image with the Dockerfile (as a best practice, I copied the project's dependencies in the requirements file before copying other application files needed, to leverage Docker's caching) in the project directory.

  • The Dockerfile contains the instructions to create the Docker image.

Dockerfile

build image

  • I created a container with the new image to test that the application worked fine. I had to exec into the container to test with curl.

fastapi container

Testing post method

Testing get method

Automate Image build and push with GitHub Actions

  • Working with the GitHub container registry (a private registry) requires generating a Personal Access Token (PAT), my password to log in to the registry and push my image.
  • To generate a Personal Access Token (PAT), navigate to settings => developer settings => personal access tokens(tokens classic) and generate a new token(classic), with read, write and delete packages permission, ensure to :
    • Give the token a name.
    • An expiration date.
    • Copy the token to a safe place as it is viewable only once.

generate PAT

  • Before setting up my workflow, I added my generated PAT and my username as a repository secret, which was used for authentication to the GitHub container registry.

how to add secrets to github

Add PAT as secret

Add username as secret

  • After adding secrets, this is what it should look like.
    Added secrets

  • To automate with GitHub actions, I created a ./github/workflows folder with a build_push.yml file containing the workflow.

build_push.yml file

build_push.yml file

  • After the workflow file is completed, initialize the repo, add files and remote origin, commit and push code to GitHub.
  • Once the code is pushed to GitHub, it triggers the workflow(the workflow is configured to trigger when there is a push or pull request event on the repository), which builds the image, logs into the registry and pushes the image.

Build succeeded

Breakdown of build

Summary of successful build

  • After pushing to the registry, the image can be viewed using this URL format: https://github.com/users/YOUR_USERNAME/packages

Image in registry

Image in registry1

Challenges encountered and fixes

  • I had a couple of unsuccessful builds, and I realised there were some rules to follow while working with GitHub container registry. I will be outlining some challenges I encountered and how I resolved them.

unsuccessful builds

Some of the challenges I encountered included:

  • I discovered that GitHub Container Registry (GHCR) requires all repository names to be in lowercase, a suggested fix was to change from tags: ghcr.io/${{ github.actor }}/fast-api-crud:latest to tags: ghcr.io/${{ github.repository_owner }}/fast-api-crud:latest (this converts username to lowercase using GitHub's toLower function)

GHCR error: repo name

  • The option above did not work, so I renamed my GitHub account (this is not advisable, but I took the risk) and removed all uppercase letters, and updated my secret.

update username

GHCR error: repo name1

  • The next error is something around organizations. I do not know much about organizations, so I deleted the organizations attached to my account (it was not useful to me anymore) and renamed the secret name for my token from TOKEN to GHCR_PAT (I also effected this change on the workflow).
    GHCR error: organization package

  • I also forgot to allow pip read the list of dependencies from the specified file (requirements.txt). I fixed it by adding the -r flag.
    GHCR error: incomplete installation

This tutorial shows how to:

  • Structure a FastAPI application for seamless containerization.
  • Write a Dockerfile to package the app into a container.
  • Automate builds and pushes using GitHub Actions.
  • Troubleshoot common issues with private container registries.

Because this setup is automated, any code changes automatically trigger a new Docker image build and push to GitHub container registry, which streamlines the deployment process.

Thank you for reading, kindly check out the repository. Till my next project, happy building! ✌🏽

Top comments (0)