ローカル(Mac)で Step Function / Lambda / DynamoDB を動かす


これなに?

ざっくりとした手順

  1. Dockerのインストール
  2. Docker HubよりLocalStackと、Step Functions Localのイメージを取得
  3. LocalStack起動
  4. DynamoDBテーブル作成
  5. Lambda関数作成
  6. Step Functions作成
  7. Step Functions起動

Dockerのインストール

Dockerが必要なので、ない場合はインストールしてください
AWS CLIも、ない場合はインストールしてください

Docker HubよりLocalStackと、Step Functions Localのイメージを取得

以下のコマンドでpullしましょう

$ docker pull localstack/localstack
$ docker pull amazon/aws-stepfunctions-local

取得できたか確認します

$ docker images

備考

https://github.com/localstack/localstack
をcloneしてきて、 docker-compose でも起動できます
こっちのほうが楽かもしれません

LocalStack起動

以下のコマンドで起動できます

$ docker run --rm -it -p 4566:4566 -p 4571:4571 localstack/localstack

備考

https://github.com/localstack/localstack に記載がありますが、
LocalStackの 0.11.0 から、DynamoDB、Lambdaなどすべてのサービスが同じポート 4566 で起動するようになったそうです

備考2

$ aws configure --profile localstack

でプロファイルを適当に定義すると良いかもですが、設定しなくても動作はするようです
設定例)

AWS Access Key ID [None]: dummy
AWS Secret Access Key [None]: dummy
Default region name [None]: us-east-1
Default output format [None]: text

DynamoDBテーブル作成

$ aws dynamodb create-table --table-name TestTable \
    --attribute-definitions AttributeName=Id,AttributeType=N \
    --key-schema AttributeName=Id,KeyType=HASH \
    --endpoint-url http://localhost:4566 \
    --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
$ aws dynamodb scan --table-name TestTable --endpoint-url http://localhost:4566

Lambda作成

関数作成

参考サイトから パクって オマージュして来たものをもとに関数を作ります
DynamoDBのエンドポイントが記載されているので、LocalStackのエンドポイントを指定します
中身は TestTable に1行だけPUTするものです
ファイル名は適当に lambda.py としています

import boto3
def lambda_handler(event, context):
    dynamodb = boto3.resource('dynamodb', region_name='us-east-1',endpoint_url='http://localhost:4566/')
    table = dynamodb.Table('TestTable')
    response = table.put_item(
        Item={
            'Id': 1,
            'Name': 'Mayoi'
        }
    )
    return response

Lambda関数を作成

作成した関数をzipにします

$ zip lambda.zip lambda.py

次にデプロイします

$ aws lambda create-function \
  --function-name=TestFunction \
  --runtime=python3.6 \
  --role=DummyRole \
  --handler=lambda.lambda_handler \
  --zip-file fileb://lambda.zip \
  --endpoint-url=http://localhost:4566

エンドポイントURLはDynamoDBと同一でOKです(LocalStackの 0.11.0 以降)

Step Functions作成

設定ファイル作成

$ vi aws-stepfunctions-local-credentials.txt 

vi で以下の内容のファイルを作成してください

LAMBDA_ENDPOINT=http://host.docker.internal:4566

LambdaのエンドポイントをStep Functionsに設定しています
他にも、もろもろ設定する場合は以下を参考にしてください
https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/sfn-local-config-options.html#docker-credentials

StepFunctions Localコンテナ起動

StepFunctionsのコンテナを起動します

docker run -p 8083:8083 --env-file aws-stepfunctions-local-credentials.txt amazon/aws-stepfunctions-local

ステートマシン作成

StepFunctionsのステートマシンを作成します
ステートマシンとはざっくり言うと、状態管理の定義かと思います
StepFunctions君は、横浜駅へ行って高島屋で日本酒買って帰ってくるみたいな指令書を定義します

参考にした記事では defin_statemachine.json というファイルにステートマシンを定義しています

{
  "StartAt": "Shinobu",
  "States": {
    "Shinobu": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:::function:TestFunction",
      "End": true
    }
  }
}

ステートマシンの定義ファイルを書いたら、以下のコマンドで実際にステートマシンを作成します

aws stepfunctions create-state-machine \
  --name TestState \
  --definition file://defin_statemachine.json \
  --role-arn "arn:aws:iam::000000000000:role/DummyRole" \
  --endpoint http://localhost:8083

うまく作成できると、以下のようなのが返ってきます

1622974168.008  arn:aws:states:us-east-1:123456789012:stateMachine:TestState

arn:aws:states:us-east-1:123456789012:stateMachine:TestState はARNです
ステートマシンを実行するときには、こいつを指定します

Step Functions起動

ステートマシンの定義ができたので、実際に実行してみます

$ aws stepfunctions start-execution \
  --state-machine arn:aws:states:us-east-1:123456789012:stateMachine:TestState \
  --endpoint http://localhost:8083

上記を実行すると、ステートマシンが起動し、Lambdaが実行され、DynamoDBに値が書き込まれるはずです
実行すると、以下のように実行のARNが払い出されるので、これを用いて結果確認も可能です

arn:aws:states:us-east-1:123456789012:execution:TestState:6a2e5112-6c3e-42d8-9359-426b66e26617  1622975148.062

結果確認は以下のようなコマンドです

$ aws stepfunctions describe-execution \
  --execution-arn arn:aws:states:us-east-1:123456789012:execution:TestState:6a2e5112-6c3e-42d8-9359-426b66e26617 \
  --endpoint=http://localhost:8083

SUCCEEDED が返ってきたら成功やで!

結果確認

DynamoDBをscanしてみて、データが入っているか確認してみましょう

$ aws dynamodb scan --table-name TestTable --endpoint-url http://localhost:4566

値が入っていたら優勝!

参考にした記事

https://dev.classmethod.jp/articles/stepfunctionslocal-localstack/
https://dev.classmethod.jp/articles/localstack-lambda/