Lambda関数でDockerコンテナ化されたPythonのFastAPIサービスを動かす

# Lambda関数でDockerコンテナ化されたPythonのFastAPIサービスを動かす
* 参考にさせていただいたブログ : https://reffect.co.jp/aws/lambda-docker-fastapi
## ディレクトリを作成する
```bash
docker -v
mkdir lambda_fastapi
cd lambda_fastapi
```
## fastAPIサービスを実装する
```bash
touch app.py
```
* ~/aws/lambda_fastapi/app.py
```python
from fastapi import FastAPI
from pydantic import BaseModel
from mangum import Mangum

class Item(BaseModel):
    name: str
    price: float

app = FastAPI()

@app.get('/')
async def root():
  return {"message": "Hello from lambda"}

@app.get("/uppercase")
async def uppercase(text: str):
    return {"message": text.upper()}

@app.post("/items")
async def create_item(item: Item):
    return item

handler = Mangum(app)
```
## ライブラリ記述ファイルを作る
```bash
touch requirements.txt
```
* ~/aws/lambda_fastapi/requirements.txt
```text
fastapi
mangum
```
## Dockerfileを作る
```bash
touch Dockerfile
```
* ~/aws/lambda_fastapi/Dockerfile
```dockerfile
FROM public.ecr.aws/lambda/python:3.12

COPY app.py ${LAMBDA_TASK_ROOT}
COPY requirements.txt ${LAMBDA_TASK_ROOT}

RUN pip install -r ./requirements.txt

CMD ["app.handler"]
```
## Dockerイメージをビルドする
```bash
docker build -t lambda_fastapi .
docker images
```
## 動作確認する
```bash
docker run -p 9000:8080 lambda_fastapi
docker ps
```
## サービスを確認する
* GETリクエスト
```bash
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"resource": "/", "path": "/", "httpMethod": "GET", "requestContext": {}}'
```
* POSTリクエスト
```bash
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" \
-d '{
  "resource": "/items",
  "path": "/items",
  "httpMethod": "POST",
  "requestContext": {},
  "body": "{\"name\": \"Keyboard\",\"price\":10000}"
}'
```

## ECRリポジトリの作成
* AWSの`prod`プロファイルに切り替え
```bash
aws ecr ls --profile prod
export AWS_PROFILE=prod
```
* 認証トークンを取得し、レジストリに対して Docker クライアントを認証
```bash
aws ecr get-login-password --region ap-northeast-1 --profile prod | docker login --username AWS --password-stdin 11111111111111111.dkr.ecr.ap-northeast-1.amazonaws.com
```
* ECRリポジトリの作成
```bash
aws ecr create-repository --repository-name lambda_fastapi_repo --profile prod --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
```
* Dockerイメージをタグ付け
```bash
docker tag lambda_fastapi:latest 11111111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/lambda_fastapi_repo:latest
docker images
```
  * 実行結果
  ```bash
  REPOSITORY                                                              TAG       IMAGE ID       CREATED          SIZE
  11111111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/lambda_fastapi_repo   latest    ee65f52d4fed   44 minutes ago   543MB
  lambda_fastapi                                                          latest    ee65f52d4fed   44 minutes ago   543MB
  ```
* イメージのアップロード
```bash
docker push 11111111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/lambda_fastapi_repo:latest
```
  * 実行結果
  ```bash
  The push refers to repository [211125541523.dkr.ecr.ap-northeast-1.amazonaws.com/lambda_fastapi_repo]
  3dded92ad458: Pushed 
  ・・・・省略・・・・
  922a9a710c9e: Pushed 
  latest: digest: sha256:dkspdksokoskodksokdoskodskodksodksokdosa size: 2203
  ```
* リポジトリ情報の確認
```bash
aws ecr describe-repositories
```
  * 実行結果
  ```bash
  {
    "repositoryArn": "arn:aws:ecr:ap-northeast-1:11111111111111111:repository/lambda_fastapi_repo",
    "registryId": "11111111111111111",
    "repositoryName": "lambda_fastapi_repo",
    "repositoryUri": "11111111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/lambda_fastapi_repo",
    "createdAt": "2024-03-30T10:42:52.223000+09:00",
    "imageTagMutability": "MUTABLE",
    "imageScanningConfiguration": {
        "scanOnPush": true
    },
    "encryptionConfiguration": {
        "encryptionType": "AES256"
    }
  }
  ```

  ## Lambda関数の作成
  * URL : https://ap-northeast-1.console.aws.amazon.com/lambda/home?region=ap-northeast-1#/functions
    * [関数の作成]
  * 関数の作成
    * コンテナイメージ : 選択
    * 関数名 : lambdaFastAPI
    * コンテナイメージ URI
      * [イメージを参照]
        * Amazon ECR イメージリポジトリ : lambda_fastapi_repo
        * イメージ : `latest`選択
        * [イメージを選択]
    * アーキテクチャ : arm64
    * [関数の作成]
![](https://storage.googleapis.com/zenn-user-upload/c97bfdce0357-20240330.png)
## 関数URLの設定
* URL : https://ap-northeast-1.console.aws.amazon.com/lambda/home?region=ap-northeast-1#/functions/lambdaFastAPI?newFunction=true&tab=image
  * [設定]
    * 一般設定
      * 関数URL
        * [関数 URL を作成]
  * 関数 URL を設定
    * 認証タイプ : NONE
    * [保存]
  * 関数URL
    * 関数URL : https://sskofeokfkeofkoekfoekofkeo.lambda-url.ap-northeast-1.on.aws

## 関数URLの確認
* サービスURL : https://sskofeokfkeofkoekfoekofkeo.lambda-url.ap-northeast-1.on.aws
  * リターン値 : `{"message":"Hello from lambda"}`
* ドキュメントURL : https://sskofeokfkeofkoekfoekofkeo.lambda-url.ap-northeast-1.on.aws/docs
  ![](https://storage.googleapis.com/zenn-user-upload/b30224224ea2-20240330.png)