FastAPIサーバーレスアプリケーションのデプロイ + 奮闘記

## はじめに
LambdaとAPI Gatewayを使用してサーバレスアプリケーションを構築します。Lambdaに直接関数を実装する方法があるが、Githubでのコード管理しやすさも考え、FastAPIで作成したものをLambdaへあげる方法にしました。

今回は下記について記載しています。
- サーバレスアプリケーションデプロイ奮闘記
- AWS SAMを使用したデプロイ手順

## サーバレスアプリケーションデプロイ奮闘記
### １. zipをLambdaにアップロードする
まずこの方法を試しました。
AWSコンソール画面を操作して手作業で構築するので、LambdaとAPI Gatewayの関連性など何が起きているのか分かりやすいので初めは多くの方がこの方法で構築すると思います。
こちらの記事が詳細な手順をご紹介してくれています。↓

https://qiita.com/Shinkijigyo_no_Hitsuji/items/cedd1825e5437663d3ce

**だができなかった...**

この手順でうまくいかない原因としてよくあるのは以下だと思います。
- 開発環境とランタイムのpythonバージョン不一致
- Lamdaのハンドラ間違い
- アーキテクチャ(x86_64 か arm64)の違い

https://qiita.com/Ryo-0131/items/680a1ee53ff86728dfe7

トライアンドエラーで構築を繰り返したができませんでした。

### ２. ECR + Docker
ECRにFastAPIを動かすDockerイメージをあげてLambdaでDockerコンテナを実行するという方法も試したがこれもうまくいきませんでした。

https://qiita.com/teruroom/items/738f21d1c57f8a757abf#lambda%E9%96%A2%E6%95%B0%E3%81%AE%E4%BD%9C%E6%88%90

### ３. AWS SAM
ようやくここにたどり着いた。結論この方法でできました。
再現性が高く、テンプレートあれば次から一瞬でデプロイできます。
下記で詳細を紹介します。

## AWS SAMでFastAPIアプリをデプロイ
### AWS SAMとは
IaC(Infrastructure as Code)を使用したサーバーレスアプリケーション構築するフレームワークです。
IaCというのはインフラ構成や設定をコード化できるもので、AWS SAMはデプロイ時にコードを元にインフラを構築してくれます。
これを使用すると手作業でLambdaやAPI Gatewayを作成する必要がなくなります。

SAMについて何も分かんない方は、AWSコンソールを触りながらチュートリアルをやるとどの項目が結びついているのかなど分かってきます。

https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html

https://aws.amazon.com/jp/builders-flash/202304/api-development-sam-fastapi-mangum/

### デプロイ手順
こちらのGithubをクローンして、Readmeの通りにやってもできます。

https://github.com/tomoya092013/FastAPI_SAM

- FastAPIでアプリ作成
とりあえずHelloWordを返す簡単なもので良い

- IAMユーザーを作成する
アクセスキーとシークレットアクセスキーが必要なので作成しておく

- FastAPIAWS CLIをインストール
```
インストール
  brew install awscli

バージョン確認
  aws --version
```

- AWS CLI の設定
デプロイするための認証情報を設定する
```
aws configure
```
```
AWS Access Key ID: 
AWS Secret Access Key: 
Default region name: 
Default output format: 

(参考)
AWS Access Key ID: アクセスキー
AWS Secret Access Key: シークレットアクセスキー
Default region name: ap-northeast-1
Default output format: json
```

- ルートディレクトリにtemplate.yamlを作成
    - 同じディレクトリのmain.pyのhandlerを実行する
    - エンドポイントが / と /testや/user 等のGETやPOSTができる
```template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Resources:
  FastApiApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Dev

  FastApiFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: .
      Handler: main.handler
      Runtime: python3.12
      MemorySize: 512
      Timeout: 30
      Events:
        RootApi:
          Type: Api
          Properties:
            RestApiId: !Ref FastApiApi
            Path: /
            Method: ANY
        ApiGatewayProxy:
          Type: Api
          Properties:
            RestApiId: !Ref FastApiApi
            Path: /{proxy+}
            Method: ANY
```
- ルートディレクトリにsamconfig.tomlを作成
    - 50MB以上のデプロイに対応するため、s3の利用をtrueにする
    - デプロイ失敗時は自動でロールバックさせる
```samconfig.toml
version = 0.1
[default.deploy.parameters]
stack_name = "fastapi"
resolve_s3 = true
s3_prefix = "fastapi"
region = "ap-northeast-1"
capabilities = "CAPABILITY_IAM"
disable_rollback = false
image_repositories = []
```


- ビルドとデプロイ
```
ソース変更したらビルド
  sam build

デプロイ
　sam deplpy

デプロイ設定（samconfig.toml）を変更したい場合
　sam deploy --guided
```
デプロイ後AWSコンソールにログインすると、LambdaとAPI Gatewayが作成されているのが確認できます。

- エンドポイントの確認方法
    - １.  sam list endpoints --stack-name [samconfig.tomlのstack_name]
    - ２.  AWS マネジメントコンソール（API Gatewayのステージ）で確認



## おわりに
SAMを使う前にAWSコンソールで何度も構築していたため、SAMへの理解が早かったと感じています。
zip化してアップロードしようとしていましたが、コマンドのみでデプロイできるこの方法を知れて良かったです。