DEV Community

loading...

Deploying a FastAPI backend using AWS Amplify Container-based REST APIs

siegerts
Open Source Solutions Architect @AWSamplify. I try to keep things simple. That, and emoji 🐶. https://twitter.com/siegerts
Originally published at xiegerts.com ・5 min read

No surprise that it's a difficult process to go from development to production deployments in an organization 🤷.

This is especially true for analytics and data science teams developing models or business logic. There's usually not a clear path or tooling to support application hand-offs or deployments across teams.

One way to bridge the gap between applications is to allow for service-to-service communication. REST APIs are great for this type of use-case. Especially when auto-generated, interactive documentation, is available out-of-the-box 😉.

AWS Amplify provides a great option for this - Serverless containers using API Gateway + AWS Fargate.

This guide will follow the steps outlined in the Serverless containers section of the Amplify documentation and the FastAPI Docker Deployment documentation to quickly create and deploy a production-ready, scalable REST API.

Prerequisites

You'll need to have the below installed and configured.

FastAPI

As mentioned above, we'll use FastAPI as the backend framework. The application pattern will feel natural if you're familiar with Flask.

FastAPI has quickly become a go-to framework for setting up APIs for data science and analytics-based workloads. From the project page:

FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.

Among some of the callouts:

Fast: Very high performance, on par with NodeJS and Go
Robust: Get production-ready code. With automatic interactive documentation.

This is a great option for data science teams that want to focus on productionalizing APIs with the ability to scale in the future if needed.

Also, as we'll see below, testing locally is a smooth process using Docker.

Serverless containers with Amplify

If you need an escape hatch from just using Lambda then this may be a great option for you. We'll walk through a more basic set up below but the same approach can be leveraged for more complex backends using a docker-compose.yml configuration.

Serverless containers provide the ability for you to deploy APIs and host websites using AWS Fargate. Customers with existing applications or those who require a lower level of control can bring Docker containers and deploy them into an Amplify project fully integrating with other resources.

Project set up

Okay, let's deploy an API.

First, create a new directory and initialize the the Amplify project. In this example, I'm not hooking up a frontend so I just select the default options. But, if a frontend is something that you're interested in, then it's possible to layer that on and have the UI (React, Vue, etc.) talk to the backend API that is being created.

Make the directory.

 mkdir fastapi-amplify
Enter fullscreen mode Exit fullscreen mode

Initialize the Amplify project.

amplify init
Enter fullscreen mode Exit fullscreen mode

Terminal workflow
Scanning for plugins...
Plugin scan successful
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project fastapiamplify
? Enter a name for the environment dev
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using none
? Source Directory Path:  src
? Distribution Directory Path: dist
? Build Command:  npm run-script build
? Start Command: npm run-script start
Enter fullscreen mode Exit fullscreen mode

Enabling container-based deployments

Now, with the project initialized, we need to enable the use of the container-based deployment options.

amplify configure project
Enter fullscreen mode Exit fullscreen mode

Alt Text

Terminal workflow
? Which setting do you want to configure? Advanced: Container-based deployments
Using default provider  awscloudformation
? Do you want to enable container-based deployments? Yes

Enter fullscreen mode Exit fullscreen mode

Adding the API

With the project configured, let's add the soon-to-be API.

amplify add api
Enter fullscreen mode Exit fullscreen mode

Alt Text

Terminal workflow
? Please select from one of the below mentioned services: REST
? Which service would you like to use API Gateway + AWS Fargate (Container-based)
? Provide a friendly name for your resource to be used as a label for this category in the project: fastapirest
? What image would you like to use Custom (bring your own Dockerfile or docker-compose.yml)
? When do you want to build & deploy the Fargate task On every "amplify push" (Fully managed container source)
? Do you want to restrict API access No
Successfully added resource fastapirest locally.
Enter fullscreen mode Exit fullscreen mode

The CLI will output some next steps for setting up the API to use a bring-your-own-container setup.

Next steps:
- Place your Dockerfile, docker-compose.yml and any related container source files in "amplify/backend/api/fastapirest/src"
- Amplify CLI infers many configuration settings from the "docker-compose.yaml" file. Learn more: docs.amplify.aws/cli/usage/containers
- Run "amplify push" to build and deploy your image
Enter fullscreen mode Exit fullscreen mode

Following the above steps, the following app/ and Dockerfile are added to the API directory in the Amplify backend.

  .
  ├── amplify/backend/api/<api-name>/src/
+ │   └── app
+ │       └── main.py
+ └────── Dockerfile

Enter fullscreen mode Exit fullscreen mode

Adding the Dockerfile

This can be modified based on the needs and requirements of the project but the below default Dockerfile will get you up-and-running immediately with FastAPI.

I've adjusted the example in the FastAPI docs to use python3.8 instead of python3.7 and added the statement to expose port 80.

# Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.8

# for Amplify 
# https://docs.amplify.aws/cli/usage/containers#deploy-a-single-container
EXPOSE 80

COPY ./app /app
Enter fullscreen mode Exit fullscreen mode

Make sure to add EXPOSE 80 to specify a port to communicate with the container. Amplify will suggest to use port 80 if you don't provide one.

Setting up the API

Now, we can add in the API logic in the main.py file within app/.

# main.py

from typing import Optional
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
    return {"item_id": item_id, "q": q}

Enter fullscreen mode Exit fullscreen mode

Testing locally

With everything in place, we can test the API using Docker. Jump into the backend API directory (i.e. where the Dockerfile is) and build the image.

cd amplify/backend/api/<api-name>/src/
Enter fullscreen mode Exit fullscreen mode

Build the image.

docker build -t fastapi .
Enter fullscreen mode Exit fullscreen mode

Now, you can run the image locally, exposed on port 80 of your localhost setup.

docker run -d --name fastapi -p 80:80 fastapi
Enter fullscreen mode Exit fullscreen mode

You'll see the auto-generated API documentation at http://127.0.0.1/redoc or http://127.0.0.1/docs.

Deploying to Amplify 🚀

Awesome! Now let's push this to Amplify.

amplify push
Enter fullscreen mode Exit fullscreen mode

When prompted, select Yes to Create the new resource.

(🚀 dev) 🐶 ➜  fastapi-amplify amplify push                                                                                  (main) ✗
✔ Successfully pulled backend environment dev from the cloud.

Current Environment: dev

| Category | Resource name | Operation | Provider plugin   |
| -------- | ------------- | --------- | ----------------- |
| Api      | fastapirest   | Create    | awscloudformation |
? Are you sure you want to continue? Yes


Enter fullscreen mode Exit fullscreen mode

After the process is complete. 👇

✔ All resources are updated in the cloud

REST API endpoint: https://<id>.execute-api.<region>.amazonaws.com
Enter fullscreen mode Exit fullscreen mode

Testing the deployed API

After being deployed, the API can be accessed using the endpoint above:

Also, the live API documentation is live at the https://<endpoint>/docs and https://<endpoint>/redoc.

/docs route

Alt Text

/redoc route

Alt Text

This is just scratching the surface of configuration options. Hope this helps you get running quickly with serverless FastAPI backends!

Discussion (0)