LocalStack環境のlambdaからdynamodbにアクセスするときは、endpointを環境変数LOCALSTACK_HOSTNAMEから読み取る

公開日: 2021年05月04日最終更新日: 2021年07月31日

LocalStack を使用し、ローカルで ApiGateway <=> Lambda <=> dynamodb の開発環境を構築する際、Lambda から dynamodb にアクセスできずに嵌りました。dynamodb には aws cli からはアクセスできていました。ApiGateway から Lamda にもアクセスできています。ただ、Lambda から dynamodb にアクセスするとエラーにもならずにレスポンスが返ってこない状態でした。

使用バージョン

バージョン依存がやや強いようなので、下記よりバージョンがかなり古い、新しい場合はうまくいかない可能性があります。

  • LocalStack version: 0.12.9.1
  • aws-cli:2.0.36

LocalStack の docker-compose.yaml

LocalStack 公式のものをコピーしています(2021 年 5 月 1 日)。endpoint は ApiGateway、Lambda、dynamodb 全て localhost:4566 で作成しています。

version: "2.1"

services:
  localstack:
    container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
    image: localstack/localstack
    network_mode: bridge
    ports:
      - "4566:4566"
      - "4571:4571"
      - "${PORT_WEB_UI-8080}:${PORT_WEB_UI-8080}"
    environment:
      - SERVICES=${SERVICES- }
      - DEBUG=${DEBUG- }
      - DATA_DIR=${DATA_DIR- }
      - PORT_WEB_UI=${PORT_WEB_UI- }
      - LAMBDA_EXECUTOR=docker
      - KINESIS_ERROR_PROBABILITY=${KINESIS_ERROR_PROBABILITY- }
      - DOCKER_HOST=unix:///var/run/docker.sock
      - HOST_TMP_FOLDER=${TMPDIR}
    volumes:
      - "${TMPDIR:-/tmp/localstack}:/tmp/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"

環境変数 LOCALSTACK_HOSTNAME を使用する

LocalStack の github README に下記の記載がありました。lambda から dynamodb や S3 にアクセスする際は、localhost ではなく LOCALSTACK_HOSTNAME を使用する。

LOCALSTACK_HOSTNAME: Name of the host where LocalStack services are available. Use this hostname as endpoint (e.g., http://${LOCALSTACK_HOSTNAME}:4566) in order to access the services from within your Lambda functions (e.g., to store an item to DynamoDB or S3 from a Lambda).

LocalStack

環境変数 LOCALSTACK_HOSTNAME は自身で設定する必要はありません。

Golang の場合

github.com/aws/aws-sdk-go/service/dynamodb を使用している時、aws.Config で Endpoint を指定します。

endpoint := os.Getenv("LOCALSTACK_HOSTNAME")
dynamo_sess, err := session.NewSession(&aws.Config{
  Endpoint:aws.String(`http://`+ endpoint +`:4566`),
})
svc := dynamodb.New(dynamo_sess)

aws.Config には Region、Credentials を指定しているケースもありましたがわたしの環境だとあってもなくても繋がりました。

endpoint := os.Getenv("LOCALSTACK_HOSTNAME")
dynamo_sess, err := session.NewSession(&aws.Config{
	Endpoint:aws.String(`http://`+ endpoint+`:4566`),
	Region:      aws.String("us-east-1"),
	Credentials: credentials.NewStaticCredentials("dummy", "dummy", "dummy"),
})

LocalStack 環境の Lambda から dynamodb にうまくアクセスできない場合は、endpoint を指定すると上手くいくかもしれません。

補足:aws cli での各リソースの確認

aws cli の LocalStack 用 profile を localstack という名前で作成している前提です。LocalStack 内にリソースが作られているかを確認します。

ApiGateway

aws --endpoint-url http://localhost:4566 apigateway get-rest-apis --profile=localstack

作成した ApiGateway へのアクセス URL

ApiGateway の作り方に依存します。LocalStack の場合、{}以外は共通のようです。curl でアクセス時、status: 'runnning'でデータが返ってくるときは 想定している URL が間違っています。

http://localhost:4566/restapis/{api-id}/{stage-name}/_user_request_/{path_part}

Lambda

aws --endpoint-url http://localhost:4566 lambda list-functions --profile=localstack

dynamodb

テーブルの確認

aws --endpoint-url=http://localhost:4566 dynamodb list-tables --profile localstack --region us-east-1

テーブル項目の確認

--table-name はテーブルの確認で調べたテーブル名にします。

aws --endpoint-url=http://localhost:4566 dynamodb scan --table-name=sample-table --profile localstack

テーブル項目の挿入

--table-name はテーブルの確認で調べたテーブル名にし、--item は作成したテーブル定義により変化します。

aws --endpoint-url=http://localhost:4566 dynamodb put-item --table-name=sample-table --item '{ "name": { "S": "sample" } }' --profile localstack

コメント

頂いたコメントは管理者のみ確認できます。表示はされませんのでご注意ください。