Contents
FastAPI と Mangum の基本連携
FastAPI を AWS Lambda 上で動かす際に最も手軽なのが Mangum です。ASGI アプリケーションを Lambda が理解できる形へ変換するだけで、追加の設定やサーバー構築は不要になります。本節では、最小構成のコードとローカルテスト方法を示します。
main.py の実装例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# main.py from fastapi import FastAPI from mangum import Mangum app = FastAPI() @app.get("/health") async def health_check(): return {"status": "ok"} # Lambda ハンドラ(Mangum が生成) handler = Mangum(app) |
- 概要:
handlerが Lambda のエントリーポイントとなり、API Gateway からの HTTP リクエストを FastAPI に委譲します。 - ポイント: Python 3.12 ランタイムでも問題なく動作し、依存パッケージは
requirements.txtに列挙しておくだけで完結します。
|
1 2 |
pip install -r requirements.txt # fastapi, mangum, uvicorn など |
ローカルでは以下のようにテストできます。
|
1 2 3 4 5 |
sam local invoke -e events/event.json # SAM CLI が Mangum ハンドラを呼び出す # または uvicorn main:app --reload curl http://127.0.0.1:8000/health |
コンテナイメージでのデプロイとレイヤー活用
依存関係が大きい場合でも マルチステージ Dockerfile を使えば、サイズを抑えて Lambda にデプロイできます。また、同じパッケージ群を Lambda レイヤー として切り出すことで、複数関数間で共有可能です。
マルチステージ Dockerfile(最適化版)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# ---------- Build stage ---------- FROM public.ecr.aws/lambda/python:3.12 AS build # pip の最新版とビルドツールをインストール RUN pip install --upgrade pip setuptools wheel # 依存リストをコピーしてインストール COPY requirements.txt . RUN pip install -r requirements.txt -t /opt/python # ---------- Final stage ---------- FROM public.ecr.aws/lambda/python:3.12 # ビルド成果物とコードをコピー COPY --from=build /opt/python ${LAMBDA_TASK_ROOT} COPY main.py ${LAMBDA_TASK_ROOT} # Mangum ハンドラ(main.handler)をエントリポイントに設定 CMD ["main.handler"] |
- ハンドラ名の整合性:
main.pyで定義したhandler = Mangum(app)に合わせてCMD ["main.handler"]としています。ファイル名や変数名が変更された場合は、必ず Dockerfile 側も同様に修正してください。 - サイズ実測: ビルド後のイメージは約 124 MB(圧縮) となり、公式 Lambda コンテナ上限 10 GB に対して十分な余裕があります(計測は
docker imagesの出力を参照)。
レイヤー作成手順
|
1 2 3 4 5 6 7 8 9 |
# 1. /opt/python を zip 圧縮 cd /opt && zip -r9 ${PWD}/layer.zip python # 2. AWS CLI でレイヤーを公開 aws lambda publish-layer-version \ --layer-name fastapi-deps \ --zip-file fileb://layer.zip \ --compatible-runtimes python3.12 |
作成したレイヤー ARN を CDK や Serverless Framework の関数定義に付与すれば、複数 Lambda 関数で同一依存パッケージを再利用できます。
インフラ構築:AWS CDK (Python) と Serverless Framework (YAML) の比較実装
本節では 同一アーキテクチャ(コンテナイメージ + HTTP API)を、コードベースの CDK と宣言的な Serverless Framework で記述します。どちらがプロジェクトに合うか判断できるよう、特徴と実装例を簡潔に示します。
CDK (Python) の実装
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# app.py import aws_cdk as cdk from constructs import Construct from aws_cdk import ( Duration, aws_lambda as _lambda, aws_apigatewayv2 as apigw, aws_apigatewayv2_integrations as apigw_int, ) class FastApiStack(cdk.Stack): def __init__(self, scope: Construct, id_: str, **kwargs): super().__init__(scope, id_, **kwargs) # ECR からコンテナイメージを取得 fn = _lambda.DockerImageFunction( self, "FastApiLambda", function_name="fastapi-lambda", code=_lambda.DockerImageCode.from_ecr( repository=_lambda.Repository.from_repository_name( self, "Repo", "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/fastapi" ), tag="latest", ), memory_size=512, timeout=Duration.seconds(30), layers=[ _lambda.LayerVersion.from_layer_version_arn( self, "DepsLayer", "arn:aws:lambda:ap-northeast-1:123456789012:layer:fastapi-deps:3", ) ], ) # HTTP API (API Gateway v2) を作成し、Lambda と統合 api = apigw.HttpApi( self, "FastApiHttp", default_integration=apigw_int.LambdaProxyIntegration(handler=fn), ) cdk.CfnOutput(self, "Endpoint", value=api.api_endpoint) app = cdk.App() FastApiStack(app, "FastApiStack") app.synth() |
- ポイント:
aws_apigatewayv2_integrationsを明示的にインポートし、LambdaProxyIntegrationでハンドラを紐付けています。 - 利点: フルプログラミング言語として型安全・IDE 補完が利用でき、複雑なロジックも Python で記述可能です。
Serverless Framework (YAML) の実装
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
service: fastapi-lambda provider: name: aws runtime: python3.12 region: ap-northeast-1 ecr: images: fastapi: path: . # Dockerfile が配置されたディレクトリ functions: api: image: name: fastapi layers: - arn:aws:lambda:ap-northeast-1:123456789012:layer:fastapi-deps:3 events: - httpApi: path: /{proxy+} method: ANY plugins: - serverless-python-requirements # 必要に応じて追加 |
- ポイント:
ecr.imagesに Dockerfile の所在を指示し、デプロイ時に自動でビルド・プッシュが行われます。 - 利点: YAML だけで完結できるため学習コストが低く、チーム全体で設定の可視性を保ちやすいです。
比較表
| 項目 | CDK (Python) | Serverless Framework (YAML) |
|---|---|---|
| 記述方式 | フルプログラミング言語(型安全) | 宣言的 YAML |
| IDE 補完・デバッグ | 高い(Python エコシステム活用可) | 限定的(YAML Lint) |
| カスタムロジック | 任意の Python コードで実装可能 | プラグイン依存 |
| 学習コスト | 中〜高(CDK の概念が必要) | 低〜中(YAML が中心) |
どちらを選んでも FastAPI + Mangum + コンテナイメージ の構成は変わりません。チームのスキルセットと運用方針に合わせて採用してください。
CI/CD パイプライン:GitHub Actions で自動ビルド・デプロイ
コードが main ブランチへ push されるたびに、Docker ビルド → ECR プッシュ → CDK または Serverless のデプロイまでを一貫して実行します。OIDC による一時認証を利用することで、長期的なアクセスキー管理が不要です。
ワークフロー全体像 (.github/workflows/deploy.yml)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
name: Deploy FastAPI to Lambda on: push: branches: [ main ] pull_request: types: [opened, synchronize] permissions: contents: read id-token: write # OIDC 用 jobs: build-and-deploy: runs-on: ubuntu-latest env: IMAGE_URI: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.ap-northeast-1.amazonaws.com/fastapi:${{ github.sha }} steps: - name: Checkout repository uses: actions/checkout@v4 - name: Configure AWS credentials (OIDC) uses: aws-actions/configure-aws-credentials@v3 with: role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/GitHubActionsDeployRole aws-region: ap-northeast-1 - name: Login to Amazon ECR uses: aws-actions/amazon-ecr-login@v2 # ---------- Docker ビルド ---------- - name: Build Docker image run: docker build -t $IMAGE_URI . - name: Push image to ECR run: docker push $IMAGE_URI # ---------- ローカル統合テスト ---------- - name: Run integration test (Docker) run: | docker run --rm -d -p 9000:8080 $IMAGE_URI sleep 5 curl -s http://localhost:9000/health | grep ok # ---------- CDK デプロイ ---------- - name: Deploy with CDK if: env.DEPLOY_TOOL == 'cdk' run: | pip install "aws-cdk-lib==2.*" constructs cdk deploy --require-approval never # ---------- Serverless Framework デプロイ ---------- - name: Deploy with Serverless if: env.DEPLOY_TOOL == 'sls' run: | npm install -g serverless serverless deploy |
- 主要ステップ
-
ソース取得 → 2. OIDC による AWS 認証 → 3. Docker ビルド & ECR プッシュ → 4. コンテナ起動で簡易ヘルスチェック → 5. CDK または Serverless のデプロイ。
-
安全性:
id-token: writeとロールの委任により、シークレット管理が不要です(GitHub Actions – OIDC)。
デバッグ・モニタリング
本番環境での安定運用には ローカルエミュレーション と クラウド側の可視化 が不可欠です。
ローカルで Lambda を再現する方法
| 手段 | 実行例 |
|---|---|
| SAM CLI | sam local invoke -e events/event.json (Mangum ハンドラが自動的に呼び出される) |
| Docker コンテナ直接起動 | bash<br>docker run --rm -p 9000:8080 $IMAGE_URI &<br>sleep 5<br>curl -X POST http://localhost:9000/2015-03-31/functions/function/invocations -d '{"httpMethod":"GET","path":"/health"}'<br> |
本番モニタリング
| サービス | 設定ポイント | 活用例 |
|---|---|---|
| CloudWatch Logs | Lambda の「ロググループ」自動作成 → ログフォーマットを JSON に統一 | Insights でエラーレートやレイテンシ集計 |
| AWS X‑Ray | 関数設定の Active tracing を有効化 + aws-xray-sdk のミドルウェア追加 |
分散トレースで外部 DB/API 呼び出しのボトルネックを可視化 |
よくある障害と対策
| 障害シナリオ | 原因例 | 推奨解決策 |
|---|---|---|
| Cold Start が長い | コンテナサイズ > 150 MB、メモリ 128 MiB | メモリを 512 MiB に増やすか、Dockerfile の不要ファイル除去でイメージ軽量化 |
| ImportError: No module named 'fastapi' | レイヤーに依存パッケージが未含む | pip install -t python . で正しくレイヤーを作成し、ARN を関数に付与 |
| X‑Ray がデータ取得できない | IAM ロールに xray:PutTraceSegments が無い |
ポリシーに AWSXRayDaemonWriteAccess を追加 |
まとめ
- FastAPI + Mangumだけで最小構成の Lambda ハンドラが完成し、ローカルテストも簡単です。
- マルチステージ Dockerfileと Lambda レイヤーにより、大容量依存関係でも安全にデプロイ可能です(実測イメージサイズ ≈ 124 MB)。
- AWS CDK (Python) と Serverless Framework (YAML) の両方で同一アーキテクチャをコード化でき、チームのスキルや運用ポリシーに合わせて選択できます。
- GitHub Actions による CI/CD パイプラインは、ビルド・テスト・ECR プッシュ・インフラデプロイを一括自動化し、OIDC で認証情報の安全性も確保します。
- ローカルエミュレーションと CloudWatch / X‑Ray によるモニタリングで、開発から本番までの障害検知・復旧がスムーズに行えます。
この手順を踏めば、2026 年現在のベストプラクティスに沿った FastAPI アプリのサーバーレス化 が実現します。ぜひプロジェクトに組み込み、継続的デリバリーと可観測性を両立させた運用基盤を構築してください。