python

FastAPI+AWS Lamndaでサーバレスアプリケーションの作成方法

サーバレスFastAPIはMangumライブラリを使用して、AWS Lambdaで実行されます。

後は、AWS APIGatewayで全てのリクエストのLambdaへのルーティングを処理するのが一連の流れです。

既に、FastAPIのアプリケーションがある前提で話を進めます。

環境はvenvで作成しているものとします。

なので、ディレクトリ構成を次のような形を想定してします。

appフォルダをFastAPIのアプリケーションフォルダ、envを仮想環境フォルダとします。

.
├── app
│   ├── __init__.py
│   └── main.py
└── env

この状態から、必要なパッケージのインストールと追記をします。

pip install mangum

インストールした、magumを使ってFastAPIインスタンスをラップします。

これでアプリケーション側のコード追記は完了です。

# main.py
from fastapi import FastAPI
from mangum import Mangum

app = FastAPI()


@app.get("/")
async def root():
    return {"message": "Hello World!"}

handler = Mangum(app)

続いて、作成したFastAPIアプリケーションをパッケージ化して、Lambdaに対応できるようにします。

Lambdaは仮想環境では実行されません。そのため、ローカルで行ったようにpip installを実行しないので、パッケージ化して全ての依存関係を内包する必要があります。

cd env/lib/python3.x/site-packages
zip -r9 ../../../../function.zip .
cd ../../../../
zip -g ./function.zip -r app

これで、パッケージ化したfunction.zipが完成しました。

後は、これをAWSに上げて設定するだけです。

AWS設定

S3バケットを作成し、そこに先程作成したzipファイルをアップロードしURLをコピーしておきます。

Lambdaのマネージドサービスに移動し、関数を作成します。

先程、S3バケットのURLをコピーしたので、次の画面の赤枠で囲まれたところクリックして、コピペします。

続いて、ランタイムの設定を編集してハンドラを変更します。

これは、uvicornを起動するときのコマンドとほぼ一緒です。

ここまでできたら、リクエストが通るか確認します。

タブをテストに切り替え、新しいイベントにチェックを入れ、テンプレートをの枠をクリックしてください。

検索窓にapiと入力すると、候補に「API Gateway AWS Proxy」が出てくるのでそちらを選択します。

任意の名前を設定し、pathを”/”に、httpMethodを”GET”に変更します。

右上にある、テストをクリックして成功と返ってくれば問題ありません。

API Gatewayの作成

先程やったのは、API Gatewayのシュミレーションなので、これを本番用に設定していきます。

API Gatewayのマネージドサービスに移動し、APIを作成します。

APIのタイプはREST APIのプライベートではない方を選択します。

プロトコルの設定は次のようにして、名前は任意につけます。

次に、ルートプロキシメソッドは全てのリクエストをFastAPILambdaに転送するようにします。

左側のサイドバーからリソースを選択し、アクションのドロップダウンボタンから、「メソッドの作成」を選び、セレクトボックスからANYを選択しチェックマークをクリックします。

続いて、ANYの統合ポイントを設定していきます。

注意点は、Lambdaプロキシ統合の使用にチェックを入れることと、Lambda関数に先程作成した名前を入力することです。

Lambda関数にアクセス許可を追加するようアラートが出ますがOKで大丈夫です。

次に、ルート以外のエンドポイントにアクセスしても良いようにプロキシを立てます。

先程と同様に、アクションドロップダウンからリソースの作成を選択し、プロキシリソースとして設定するにチェックを入れてリソースを作成します。

また同じように、Lambda関数に同じ値を入れて完成です。

最後に、アクションドロップダウンからAPIのデプロイを選択し、ポップアップ画面に次のように設定したら完成です。

URLの呼び出しから、リンク先に飛ぶとローカルと同じように表示されるはずです。