Deploying Your Dockerized FastAPI Project to Heroku
Overview
The time has come! You’ve tested your FastAPI project locally and you are ready to get it up in the cloud. You can use any cloud service provider for this of course, but in this guide, we will be walking through the steps to deploy your containerized FastAPI project to Heroku. Let’s get started!
Prerequisites
Before we begin, you’ll first need to have a Heroku account, the Heroku CLI installed and locally authed in, and your FastAPI project already set up with its Dockerfile. If you haven’t Dockerized your project yet, check out the Dockerizing Your FastAPI Project post for a brief guide to get you started.
Setup
Creating the Project
In Heroku, create a new app. It can have any region and any name. I recommend giving it a descriptive name like {appname}-{dynotype}-{stage} (e.g. bookapi-web-dev).
App Config Vars
Before deploying, you may want to add your env vars to the app config for anything required to run your application. In the Heroku dashboard, navigate to the app’s settings page to add these.
Build and Deploy
This step will be broken down into two parts. The first part will contain the more common steps for those not using the Macbooks with the M1/M2 chips and the second part for those that are.
For non-M1/M2 Macbook users, you can sign into the Heroku container registry and then do a push and release. The push will set the latest in the registry while the release the changes for use. For this, teams can name their Dockerfile as Dockerfile.web or Dockerfile.worker if they have multiple dyno types being released within the same project. Alternatively, they can use a heroku.yml file to help with this. In this example, it is assumed your Dockerfile is named Dockerfile.web. The commands for these steps are as follows:
heroku container:login
heroku container:push -a appname
heroku container:release web -a appname
If you are a M1/M2 Macbook user, the step that we will replace is the upload or push step. In this case, many of us were having issues with the startup, ending up with an exec format error
. A workaround for this is to specify the platform during the build and then instead of using the heroku container:push
command, we will use the push command using the Docker CLI. The modified commands for this setup are as follows:
heroku container:login
docker build --platform linux/amd64 -t imagename -f Dockerfile.web .
docker tag imagename registry.heroku.com/appname/web
docker push registry.heroku.com/appname/web
heroku container:release web -a appname
Testing
Now that your changes are deployed, you can flip your dyno count for this app to 1 and let it rip! Check the logs to confirm the app is not crashing by running the following in terminal:
heroku logs -t -a appname
To get the standard output from your app alone, run the following:
heroku logs -t -s app -a appname
If you are seeing a successful application startup and no crashing statements, you are in business! Now you can move on to testing your new app fully. You will be able to retrieve the base URL for your app under the Settings page. Click on that URL and add any other route information for your website. If you are strictly using this setup for a headless API, try placing your base URL in a REST client like Postman to get started.
That’s it! This was just a brief example of using Heroku for both the registry and hosting the application. You can use much of the same app setup and build steps to deploy to AWS instead (which will require an AWS account and AWS CLI instead, of course), as discussed in my new book, Building Serverless Python Apps Using FastAPI and AWS. Thanks for reading and as always, Happy Hacking!