DEV Community

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

Posted on • Edited 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)