DEV Community

Cover image for How to deploy FastAPI app using AWS CDK Typescript
Nari
Nari

Posted on • Updated on

How to deploy FastAPI app using AWS CDK Typescript

Introduction

In this post, I will explain how to deploy FastAPI to a Lambda function, using the Typescript-based AWS CDK.

Prerequisite

This article is intended for those who have experience building Lambda functions and API Gateways with Typescript-based AWS CDK.

  • Setup of AWS CDK and AWS CLI is omitted.
  • Python setup is omitted.
  • FastAPI description is omitted.

Development Environment

  • node v18.5.0
  • CDK 2.83.1
  • Python 3.11.3

Install the following

pip install fastapi
pip install mangum
pip install uvicorn
Enter fullscreen mode Exit fullscreen mode

Create the app

mkdir sample-ts-fastapi
cd sample-ts-fastapi
cdk init --language typescript
npm install @aws-cdk/aws-lambda-python-alpha
Enter fullscreen mode Exit fullscreen mode

Reference
@aws-cdk/aws-lambda-python-alpha

Defining Lambda and API Gateway

Modify lib/sample-ts-fastapi-stack.tsas follows.

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";

import { PythonFunction } from "@aws-cdk/aws-lambda-python-alpha";
import { Runtime } from "aws-cdk-lib/aws-lambda";
import { LambdaRestApi } from "aws-cdk-lib/aws-apigateway";

export class SampleTsPyFastapiStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const apiName = `SampleApi`;
    const lambdaName = `MyLambda`;

    const lambda = new PythonFunction(this, lambdaName, {
      entry: "lambda",
      runtime: Runtime.PYTHON_3_10,
      index: "main.py",
      handler: "handler",
      environment: {},
    });
    const api = new LambdaRestApi(this, apiName, {
      handler: lambda,
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Create Lambda Function

The directory and file structure should be as follows.
Create main.py and user.py.

lambda/
 ├ main.py
 ├ router/
   └ user.py
Enter fullscreen mode Exit fullscreen mode

main.py

from fastapi import FastAPI
from mangum import Mangum
from .routers import user

app = FastAPI()


@app.get("/", tags=["root"])
async def root():
    return {"message": "Hello World"}

app.include_router(user.router)

handler = Mangum(app, lifespan="off")
Enter fullscreen mode Exit fullscreen mode

user.py

from fastapi import APIRouter


router = APIRouter()

@router.get("/user", tags=["user"])
async def getUser():
    return {"message": "test user"}
Enter fullscreen mode Exit fullscreen mode

Let’s try to run it in this state.

uvicorn lambda.main:app --reload
Enter fullscreen mode Exit fullscreen mode

The API created on this page is now displayed. http://127.0.0.1:8000/docs

Deploy

  • Modify from routers import user in main.py. (It did not pass at .routers.)
  • Launch Docker in advance
cdk deploy
Enter fullscreen mode Exit fullscreen mode

Adding the lambda layer

Since we are using FastAPI and Mangum, we create and add two layer.
There is also a way to include the Lambda Layer with the CDK and deploy it, but this time we did it by creating it separately.

  1. Create s3 bucket
  2. Zip the Python library
  3. Upload zip to s3
  4. Copy its Object URL
  5. Create layers from the lambda page (Object URL is required)
  6. Once the layer is created, copy its ARN

For 2 and 3, for example, create it this way.

pip install -t python/ fastapi
zip -r layer1.zip python
aws s3 cp layer1.zip s3://{backet name}/layer1.zip
Enter fullscreen mode Exit fullscreen mode

Now that we have created two layers, FastAPI and Mangum, we can add them to the lambda function described earlier.

From the Lambda page of the AWS console, go to the function details page and add two layers. Enter the ARN from earlier here.

This completes the setup.


Conclusion

That’s it, I was able to get Python’s FastAPI to work with Lambda on the Typescript-based AWS CDK.

However, I could not figure out why the import path in the main.py code would not pass in Lambda unless I did it this way.

I am a beginner in Python. If there is a way to write code that can be executed without worrying about the difference between the path environment on Lambda and the local path environment, I would appreciate it if someone could tell me.

Top comments (0)