🫠

LocalStackでLambda(TS)関数をinvokeしようとしたらつまずいた

に公開

この記事について

LocalStackのLambdaでTS関数を作ってローカルでテストしようとしたらinvokeできなくて躓いたところから立ち上がるところまで書いてあります。

これを読んだら何が得られる?

  • LocalStackのDockerComposeを用いてLambda関数の実行の正しいもの
  • Lambda(TS)関数のローカルテストが実行できるようになる

tl;dr

dockercompose.yamlにおいてのコンテナネームをちゃんと定義しよう。

container_name: localstack
~~~yaml
environment:
      - MAIN_CONTAINER_NAME=localstack
~~~

LocalStackとは

AWS系のサービスをローカルで立ち上げてローカル上で実行することが可能になるもの。
Lambda、S3などがモック可能で、Lambda関数を作る際にローカルでテストすることが可能になり、お金を気にすることなく開発できるようになる。

筆者が何をしたかったか

LocalStackを用いてLambda関数をローカルでデプロイする前にテストしたかった。

何で躓いたのか

以下のdockercompose.yamlで実行していた。

docker-compose.yaml
services:
  localstack:
    image: localstack/localstack
    ports:
      - "127.0.0.1:4566:4566"      # LocalStack Gateway
      - "127.0.0.1:4510-4559:4510-4559"  # external services port range
    environment:
      - AWS_DEFAULT_REGION=ap-northeast-1
      - DEBUG=1
      - SERVICES=lambda,events,s3,logs,sts
      - DOCKER_HOST=unix:///var/run/docker.sock
      - LS_LOG=DEBUG
      - HOSTNAME=localstack
      - HOSTNAME_EXTERNAL=localstack
    volumes:
      - "${TMPDIR:-/tmp}/localstack:/var/lib/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"

そして、以下のコマンド達を実行していた。

docker compose up -d
awslocal lambda create-function --functio-name test --role arn:aws:iam::000000000000:role/lambda-role --runtime nodejs20.x --handler dist/handler.handler --zip-file fileb://deployment.zip
awslocalについて

awslocalというのはawscliをラップしてるもので一々localstackに対してAWSCLIコマンドを打つときに--endpoint-urlを打たなくても実行できるものです。AWSCLI-LOCAL

実行してるコードの中身は

handler.ts
export const handler = async () => {
    console.log('hello, lambda function');
    return {
        statusCode: 200,
        body: JSON.stringify({
        message: 'successfully',
        }),
    };
}
awslocal lambda invoke --function-name test --payload '{}' response.json

この最後のinvokeコマンドがうまくいっていなかった。

response
takumi0706@takumis-MBP localstack-lambda-test % aws --endpoint-url http://localhost:4566 lambda invoke --function-name test --payload '{}' response.json

Read timeout on endpoint URL: "http://localhost:4566/2015-03-31/functions/test/invocations"

なんかわからないけども、タイムアウトしてしまう。
この叩く時点でタイムアウトしてしまうのは中のコードが悪いんじゃなくて実行環境(localstack)が悪いことはわかったが、解決方法が何もわからなかった。

原因

原因はとてもひどくて、docker-compose.yamlの設定ミスだった。
このサイトを見るとわかる。

セットアップにおいて注意すべきこと
下記の3点が必要です

  • MAIN_CONTAINER_NAME 環境変数

うん、MAIN_CONTAINER_NAME入れてなかった。
などの次のように修正してたら治った!!

services:
  localstack:
    image: localstack/localstack
    container_name: localstack

    ports:
      - "127.0.0.1:4566:4566"      # LocalStack Gateway
      - "127.0.0.1:4510-4559:4510-4559"  # external services port range
    environment:
      - MAIN_CONTAINER_NAME=localstack
      - AWS_DEFAULT_REGION=ap-northeast-1
      - DEBUG=1
      - SERVICES=lambda,events,s3,logs,sts
      - DOCKER_HOST=unix:///var/run/docker.sock
      - LS_LOG=DEBUG
      - HOSTNAME=localstack
      - HOSTNAME_EXTERNAL=localstack
    volumes:
      - "${TMPDIR:-/tmp}/localstack:/var/lib/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"

全部コンテナ名をlocalstackで明記したら実行できるようになった。
ほんと、ちゃんとドキュメントを自分は読んでほしいと思った。

Discussion