動機
"ちょっと"大きいコンテナイメージのAPIサーバをAWS Lambdaで動かしたい
環境
- Python 3.9
- aws-lambda-powertools 2.15.0
コード
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
# 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
する必要もないですが、変更漏れが怖いので。。
$ 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
等々テストしたいパラメータに書き換えて実行します。
INFOログもCloudWatchに出ています。(ログ出力レベルを調整しないとDEBUGは出ないようですね)
以上です!