皆様、ごきげんよう。
今回は サーバー機能を内蔵したフレームワークで構築されたアプリケーションを、簡単に AWS Lambda にデプロイする方法をご紹介します!
使用するもの#
今回の主役は aws-lambda-web-adapter です!
AWS Lambda Web Adapter は、AWS Lambda 上の 内部拡張機能 として稼働し、AWS Lambda のレスポンスを HTTP リクエストに変換するリバースプロキシ機能を持つものです。
- デプロイしたい HTTP アプリケーション → AWS Lambda のエントリーポイントに配置するだけ
- AWS Lambda Web Adapter → イベント受け取り + HTTP リクエストのフォワード
また、様々な言語・ランタイムの汎用性を持たせるために、今回は OCI コンテナイメージで Lambda 関数を作成する例とします。
WEB アプリケーション部分の用意#
今回は FastAPI + uvucorn でアプリケーション部分を記述します。
準備#
今回は仮想環境管理に uv を使用します。必要なパッケージを追加しておきます。
uv init
uv add fastapi uvicornアプリケーションコード#
メインのアプリケーションコードは非常にシンプルなものとします。
GET /→ 固定値を返しますPOST /events→ 受け取った Event JSON をそのまま返します。
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def greet():
return {"message": "Hello, World!"}
@app.post("/events")
def read_event(event: dict):
return eventまたモジュール認識させるために、src/__init__.py も空のファイルとして作成します。
HTTP リクエスト以外のイベントについて#
AWS Lambda Web Adapter は、HTTP 以外の Lambda イベントも受け取ることができ、このイベントはデフォルトで POST /events にリクエストが転送されます。これを利用することで、バッチサーバーなども簡単に Lambda 化できるということです。
- HTTP リクエスト (API Gateway, Function URLs など) → そのままのメソッド・パス
- HTTP リクエスト以外 (SQS, SNS, カスタムイベントなど) → POST
/eventsにリクエスト
なお、Event のリクエストパスは 設定(環境変数) で変更することができます。
AWS Lambda へのデプロイ#
イメージの作成#
AWS Lambda にデプロイするためのイメージを作成します。2行目で AWS Lambda Web Adapter を拡張機能に追加しています。
また、エントリーポイントは AWS Lambda の RIC のエントリーポイントではなく、メインの WEB アプリケーションの部分でよいため、非常に直感的です。
FROM ghcr.io/astral-sh/uv:python3.12-alpine
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.1 /lambda-adapter /opt/extensions/lambda-adapter
ENV AWS_LWA_PORT=8000
WORKDIR /var/task
ENV PYTHONPATH=/var/task
COPY ./src ./src
COPY ./pyproject.toml ./uv.lock ./
RUN uv sync
ENV UV_CACHE_DIR=/tmp/uv
CMD ["uv", "run", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
作成したイメージはタグ打ちして ECR に push しておきます。
AWS Lambda へのデプロイ・テスト#
特殊な手順は不要で、既に AWS Lambda にデプロイできる状態となっています。
API Gateway Http API のイベントから、GET / にリクエストするようにして確認します。
Function URLs でも確認してみます。
また、HTTP でないイベントも送ってみます。このイベントはエコーするように POST /events で設定したので正常に動いています!
まとめ#
AWS Lambda Web Adapter を使用すれば、アプリケーションコードの変更なしで AWS Lambda にデプロイできました!
ただし、Spring などの起動に時間がかかるフレームワークの場合、Provisioned concurrency の設定などの考慮が必要です。
