LoginSignup
2
2

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

Last updated at Posted at 2023-06-02

動機

"ちょっと"大きいコンテナイメージの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等々テストしたいパラメータに書き換えて実行します。
image.png

image.png

INFOログもCloudWatchに出ています。(ログ出力レベルを調整しないとDEBUGは出ないようですね)
image.png

以上です!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2