{"id":25654430,"url":"https://github.com/iwstkhr/aws-lambda-web-adapter-fastapi-example","last_synced_at":"2025-02-23T20:42:19.007Z","repository":{"id":252676305,"uuid":"841074946","full_name":"iwstkhr/aws-lambda-web-adapter-fastapi-example","owner":"iwstkhr","description":"Example of FastAPI using Lambda Web Adapter","archived":false,"fork":false,"pushed_at":"2025-02-21T22:06:28.000Z","size":119,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-23T20:42:15.383Z","etag":null,"topics":["aws","lambda","lambda-web-adapter"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iwstkhr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-11T15:10:32.000Z","updated_at":"2025-02-22T06:02:08.000Z","dependencies_parsed_at":"2025-02-21T23:19:21.888Z","dependency_job_id":"1e7f4aa8-8f50-4ae9-afb4-f937b956e7de","html_url":"https://github.com/iwstkhr/aws-lambda-web-adapter-fastapi-example","commit_stats":null,"previous_names":["iwstkhr/fast-api-using-lambda-web-adapter","iwstkhr/aws-lambda-web-adapter-fastapi-example"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwstkhr%2Faws-lambda-web-adapter-fastapi-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwstkhr%2Faws-lambda-web-adapter-fastapi-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwstkhr%2Faws-lambda-web-adapter-fastapi-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwstkhr%2Faws-lambda-web-adapter-fastapi-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iwstkhr","download_url":"https://codeload.github.com/iwstkhr/aws-lambda-web-adapter-fastapi-example/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240378873,"owners_count":19792039,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","lambda","lambda-web-adapter"],"created_at":"2025-02-23T20:42:16.217Z","updated_at":"2025-02-23T20:42:18.970Z","avatar_url":"https://github.com/iwstkhr.png","language":"TypeScript","readme":"## Introduction\n\n[Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter) has revolutionized application development on AWS Lambda. It allows developers to build backend services using Docker, a tool familiar to most developers.\n\nThis repository guides you through the process of developing API backends with [FastAPI](https://fastapi.tiangolo.com/) using Lambda Web Adapter.\n\n## Overview\n\n### Traditional Design\n\nThe traditional AWS design using API Gateway and multiple Lambda functions can become unwieldy when managing many APIs:\n\n![](./docs/images/aws-design-traditional.svg)\n\n### Design Using Lambda Web Adapter\n\nLambda Web Adapter simplifies the architecture, requiring only a single API Gateway route and one Lambda function:\n\n![](./docs/images/aws-design-lambda-web-adapter.svg)\n\n## Getting Started\n\n### Bootstrapping AWS CDK Environment\n\nFirst, bootstrap your AWS CDK environment.\n\n\u003e [!NOTE]\n\u003e You can skip this step if you've already done it.\n\nFollow the [AWS CDK guide](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_install) to install AWS CDK locally:\n\n```shell\nnpm i -D aws-cdk\nnpx cdk bootstrap aws://\u003cAWS_ACCOUNT_ID\u003e/\u003cAWS_REGION\u003e\n```\n\n### Initializing a CDK Project\n\nTo initialize your CDK project, run the following command:\n\n```shell\nmkdir cdk \u0026\u0026 cd cdk\nnpx cdk init app --language typescript\n```\n\n### Setting up FastAPI\n\nInstall FastAPI with the following commands:\n\n```shell\npython -m venv .venv\nsource .venv/bin/activate\npip install \"fastapi[standard]\"\nmkdir src\npip freeze \u003e ./src/requirements.txt\n```\n\n## Backend API using FastAPI\n\n### Writing an API\n\nHere's an example FastAPI application saved to `./src/main.py`:\n\n```python\nfrom typing import Union\n\nfrom fastapi import FastAPI\n\napp = FastAPI()\n\n\n@app.get(\"/\")\ndef read_root():\n    return {\"Hello\": \"World\"}\n\n\n@app.get(\"/items/{item_id}\")\ndef read_item(item_id: int, q: Union[str, None] = None):\n    return {\"item_id\": item_id, \"q\": q}\n```\n\n### Testing the API\n\nStart the FastAPI server with:\n\n```shell\nfastapi dev ./src/main.py\n```\n\nTest the API with your preferred tool:\n\n```shell\ncurl \"http://127.0.0.1:8000/\"\n{\"Hello\":\"World\"}\n\ncurl \"http://127.0.0.1:8000/items/1?q=keyword\"\n{\"item_id\":1,\"q\":\"keyword\"}\n```\n\n## Containerizing using Docker\n\n### Dockerfile\n\nTo containerize the FastAPI backend, write the following code and save it to `./docker/Dockerfile`. This Dockerfile is designed to handle both development and production environments effectively.\n\n**Key points:**\n\n- **Base Image**: We use [`public.ecr.aws/docker/library/python:3.12-alpine`](https://gallery.ecr.aws/docker/library/python) as our lightweight and secure base image (line 2).\n- **Lambda Web Adapter**: The Lambda Web Adapter is added for seamless AWS Lambda integration (line 22).\n- **Port Configuration**: The backend listens on **port 8080** by default for production to match the Lambda Web Adapter's expected configuration (line 25).\n\nFor more details on Lambda Web Adapter usage, refer to its [official documentation](https://github.com/awslabs/aws-lambda-web-adapter?tab=readme-ov-file#usage).\n\n```dockerfile line=\"2,22,25\"\n# Base image: Python 3.12 Alpine\nFROM public.ecr.aws/docker/library/python:3.12-alpine AS base\nENV APP_ROOT=/code\n\n# Copy requirements and install dependencies\nCOPY ./src/requirements.txt $APP_ROOT/\nRUN pip install --no-cache-dir --upgrade -r $APP_ROOT/requirements.txt\n\n# Development stage\nFROM base AS dev\nENV ENV=dev\nEXPOSE 8000\nCMD [\"sh\", \"-c\", \"fastapi run $APP_ROOT/main.py --port 8000\"]\n\n# Production stage\nFROM base\nENV ENV=prod\nEXPOSE 8080\nCOPY ./src $APP_ROOT\n\n# Copy Lambda Web Adapter\nCOPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter\n\n# Run FastAPI backend on port 8080 for Lambda Web Adapter\nCMD [\"sh\", \"-c\", \"fastapi run $APP_ROOT/main.py --port 8080\"]\n```\n\nIn the next step, we will set up Docker Compose to streamline local development and testing.\n\n### Docker Compose for Local Development\n\nWhile this repository does not include database usage, in real-world scenarios, you often work with databases such as DynamoDB, MySQL, or others. To facilitate local development and testing, we can set up Docker Compose.\n\nCreate a `./docker/compose.yaml` file with the following content:\n\n```yaml\nservices:\n  api:\n    build:\n      context: ../\n      dockerfile: ./docker/Dockerfile\n      target: dev\n    ports:\n      - \"8000:8000\"\n    volumes:\n      - ../src:/code\n```\n\n#### Key Configuration Details\n- **Build Context**: Points to the project root (`../`) and uses the development stage of the Dockerfile (`target: dev`).\n- **Ports Mapping**: Maps the container's port `8000` to the host's port `8000` for local access.\n- **Volumes**: Mounts the local `src` directory to the container's `/code` directory to enable hot-reloading of code during development.\n\n#### Running the Backend Service\n\nTo start the backend service locally using Docker Compose, run the following commands:\n\n```shell\ncd docker\ndocker compose up\n```\n\nWhen the service starts successfully, you should see logs similar to:\n\n```plaintext\napi-1  | INFO:     Started server process [1]\napi-1  | INFO:     Waiting for application startup.\napi-1  | INFO:     Application startup complete.\napi-1  | INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)\n```\n\nYou can now access the API at `http://127.0.0.1:8000` and test it as usual using tools like `curl`, Postman, or a browser.\n\nNext, we will explore deploying the FastAPI application to AWS Lambda using AWS CDK.\n\n## Deploying to AWS\n\n### Defining AWS Resources using AWS CDK\n\nTo deploy the FastAPI backend to AWS, define the necessary resources using AWS CDK. The CDK simplifies resource creation by allowing you to define infrastructure in code.\n\n#### Step 1: Configure the Entry Point\n\nPaste the following code into `cdk/bin/cdk.ts`. This is the entry point for your AWS CDK application.\n\n```typescript\n#!/usr/bin/env node\nimport 'source-map-support/register';\nimport * as cdk from 'aws-cdk-lib';\nimport { CdkStack } from '../lib/cdk-stack';\n\nconst app = new cdk.App();\nnew CdkStack(app, 'App');\n```\n\n#### Step 2: Define the Infrastructure Stack\n\nIn `cdk/lib/cdk-stack.ts`, define the AWS Lambda function and API Gateway. The following code creates a Dockerized Lambda function and integrates it with an API Gateway REST API.\n\n```typescript line=\"20,23\"\nimport * as cdk from 'aws-cdk-lib';\nimport type { Construct } from 'constructs';\nimport { LambdaRestApi } from 'aws-cdk-lib/aws-apigateway';\nimport {\n  DockerImageCode,\n  DockerImageFunction,\n  LoggingFormat,\n} from 'aws-cdk-lib/aws-lambda';\nimport * as path from 'node:path';\nimport { Platform } from 'aws-cdk-lib/aws-ecr-assets';\n\nexport class CdkStack extends cdk.Stack {\n  constructor(scope: Construct, id: string, props?: cdk.StackProps) {\n    super(scope, id, props);\n\n    // Dockerized Lambda Function\n    const lambda = new DockerImageFunction(this, 'function', {\n      functionName: 'fast-api-app-function',\n      loggingFormat: LoggingFormat.JSON,\n      memorySize: 512, // Larger memory to avoid timeout\n      code: DockerImageCode.fromImageAsset(path.join(__dirname, '..', '..'), {\n        file: path.join('docker', 'Dockerfile'),\n        platform: Platform.LINUX_AMD64, // Required for Apple Silicon users\n        exclude: ['*', '!src', '!docker'],\n      }),\n    });\n\n    // API Gateway REST API\n    new LambdaRestApi(this, 'api', {\n      handler: lambda,\n      deploy: true,\n    });\n  }\n}\n```\n\n##### Keynotes\n- **Memory Size**: Set `memorySize` to 512 MB or higher (line 20). This prevents potential timeouts caused by insufficient memory.\n- **Platform Configuration**: Use `Platform.LINUX_AMD64` (line 23) if you are using Apple Silicon. Without this, you may encounter the error: `Error: fork/exec /opt/extensions/lambda-adapter: exec format error Extension.LaunchError`.\n\nWith these files in place, you're ready to deploy your resources.\n\n#### Step 3: Deploy the Resources\n\nNavigate to your CDK project directory and run the following command to deploy:\n\n```shell\ncd cdk\nnpx cdk deploy\n```\n\nDuring deployment, you may be prompted to confirm resource creation. Respond with `y` to proceed:\n\n```plaintext\nDo you wish to deploy these changes (y/n)? y\nApp: deploying... [1/1]\nApp: creating CloudFormation changeset...\n\n ✅  App\n\n✨  Deployment time: 52.67s\n\nOutputs:\nApp.apiEndpoint9349E63C = https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/\nStack ARN:\narn:aws:cloudformation:\u003cAWS_REGION\u003e:\u003cAWS_ACCOUNT_ID\u003e:stack/App/\u003cUUID\u003e\n\n✨  Total time: 55.42s\n```\n\nThe deployment will output the API Gateway endpoint, which you can use to test your API.\n\n### Testing the App\n\nTest the deployed APIs:\n\n```shell\ncurl \"https://\u003cAPI_GATEWAY_ENDPOINT\u003e/prod/\"\n{\"Hello\":\"World\"}\n\ncurl \"https://\u003cAPI_GATEWAY_ENDPOINT\u003e/prod/items/1?q=keyword\"\n{\"item_id\":1,\"q\":\"keyword\"}\n```\n\n## Conclusion\n\nLambda Web Adapter significantly simplifies API development on AWS Lambda by reducing complexity and facilitating local testing capabilities. With its ability to streamline AWS architectures, it is an invaluable tool for modern web development.\n\nHappy Coding! 🚀\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiwstkhr%2Faws-lambda-web-adapter-fastapi-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiwstkhr%2Faws-lambda-web-adapter-fastapi-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiwstkhr%2Faws-lambda-web-adapter-fastapi-example/lists"}