AWS LambdaでAPIサーバーを作りたい(コンテナで)

# 動機
"ちょっと"大きいコンテナイメージのAPIサーバをAWS Lambdaで動かしたい

# 環境
* Python 3.9
* aws-lambda-powertools 2.15.0

# コード
Dockerfile
```Dockerfile
FROM public.ecr.aws/lambda/python:3.9
RUN pip install -t . aws-lambda-powertools==2.15.0
COPY app.py ${LAMBDA_TASK_ROOT}
CMD [ "app.handler" ]
```
app.py
```python
# c.f. https://aws.amazon.com/jp/builders-flash/202209/lambda-powertools-python-5/
# c.f. https://dev.classmethod.jp/articles/aws-lambda-powertools-python/
import json
from typing import Any, Dict
from aws_lambda_powertools import Logger
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
# API Gatewayではなく関数URLで呼出しする場合
# from aws_lambda_powertools.event_handler import LambdaFunctionUrlResolver
from aws_lambda_powertools.utilities.typing import LambdaContext
from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent

logger = Logger()
app = APIGatewayRestResolver()
# API Gatewayではなく関数URLで呼出しする場合
# app = LambdaFunctionUrlResolver()

@app.get("/")
def abc():
    return {"root": "here"}

@app.post("/")
def efg():
    return {"root": "post"}


@app.get("/say")
def say():
    return {"good": "night"}

@logger.inject_lambda_context(log_event=True)
def handler(event: APIGatewayProxyEvent, context: LambdaContext) -> Dict[str, Any]:
# API Gatewayではなく関数URLで呼出しする場合
# def handler(event, context):
    logger.debug("デバッグ")
    logger.info("情報")
    return app.resolve(event, context)
```

# まずローカルでコンテナイメージをビルドして実行
`localhost:9000`以降のパスは`public.ecr.aws/lambda/python`をベースイメージに使ったときのおまじないです。APIサーバーとして受け付けるパスは`-d`以降にあるjson内の`"path": "/"`部分を書き換えてください。
```
$ docker build -t hello-world .
$ docker run -p 9000:8080 hello-world
$ curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{  "body": "xxxxx", "path": "/say", "httpMethod": "GET", "queryStringParameters": {"foo": "bar"}}'
{"statusCode": 200, "body": "{\"good\":\"night\"}", "isBase64Encoded": false, "multiValueHeaders": {"Content-Type": ["application/json"]}}
```

# AWS ECRにプッシュしてLambdaを作ってテスト
まずコンテナイメージのPush先となるECRリポジトリを作成してください。操作は割愛します。
※ECRリポジトリ名は後述のコマンドの`YOUR_ECR_REPOSITORY_NAME`と名前を合わせてください。

`export`してる部分とAWSプロファイル名は適切に変更してください。こんな無理に`export`する必要もないですが、変更漏れが怖いので。。
```bash
$ export ecr_label=yyyyMMdd_n;
$ export ecr_image_name=YOUR_ECR_REPOSITORY_NAME;
$ export ecr_aws_domain=YOUR_AWS_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com
$ aws ecr --profile YOUR_AWS_PROFILE get-login-password --region ap-northeast-1
$ docker login --username AWS --password-stdin ${ecr_aws_domain}
$ docker build -t ${ecr_image_name} .
$ docker tag ${ecr_image_name}:latest ${ecr_aws_domain}/${ecr_image_name}:${ecr_label}
$ docker push ${ecr_aws_domain}/${ecr_image_name}:${ecr_label}
```

次にAWS Lambdaでコンテナイメージを選択して関数を作成して下さい、操作は割愛します。

AWS Lambdaのテストのテンプレートから`API Gateway AWS Proxy`を選択して、
`path`等々テストしたいパラメータに書き換えて実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128458/b4871292-85e3-fac8-3e68-0200869646ea.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128458/4cf0de1f-47fa-3d27-1417-65cde3f7685e.png)

INFOログもCloudWatchに出ています。(ログ出力レベルを調整しないとDEBUGは出ないようですね）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128458/4a26a29c-0a5a-6cc6-1406-90e2c3aa0cca.png)

以上です！