docker
sam
lambda
stepfunctions

Step Functions と Lambda をローカルで実行するときのハマりどころ


はじめに

StepFunctions を local で実行するための Docker Image amazon/aws-stepfunctions-local が公開されました。

公式チュートリアルにしたがって StepFunctions と Lambda Function をローカルで実行してみたときの手順メモ。

Docker Container を起動するときの環境変数周りでハマりました。。


手順


SAM アプリケーションの作成

公式チュートリアルにしたがって、HellorWorldFunction のSAMアプリケーションを作成します。


API のエンドポイントの確認

$ sam local start-api

エンドポイントにアクセスする

$ curl http://127.0.0.1:3000/hello

{"message":"hello world"}


Lambda Function をローカルで起動する

$ sam local start-lambda

2019-02-11 00:19:31 Found credentials in environment variables.
2019-02-11 00:19:31 Starting the Local Lambda Service. You can now invoke your Lambda Functions defined in your template through the endpoint.
2019-02-11 00:19:31 * Running on http://127.0.0.1:3001/ (Press CTRL+C to quit)


Docker コンテナの環境変数を指定する

資料にあるとおり、Dockerイメージに環境変数を与える必要があります。


aws-credentials.txt

AWS_ACCOUNT_ID=123456789012

AWS_DEFAULT_REGION=us-east-1
AWS_ACCESS_KEY_ID=dummy
AWS_SECRET_ACCESS_KEY=dummy
LAMBDA_ENDPOINT=http://host.docker.internal:3001


ローカル環境変数を指定


.envrc

export AWS_DEFAULT_REGION=us-east-1

export AWS_REGION=us-east-1
export AWS_ACCOUNT_ID=123456789012
export AWS_ACCESS_KEY_ID=dummy1
export AWS_SECRET_ACCESS_KEY=dummy


StepFunctions をローカルで起動

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


ローカルの StepFunctions に state machine を作成する

$ aws stepfunctions --endpoint http://localhost:8083 create-state-machine --definition "{\

\"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Local function\",\
\"StartAt\": \"HelloWorld\",\
\"States\": {\
\"HelloWorld\": {\
\"Type\": \"Task\",\
\"Resource\": \"arn:aws:lambda:us-east-1:123456789012:function:HelloWorldFunction\",\
\"End\": true\
}
\
}
\
}
\
}}"
--name "HelloWorld" --role-arn "arn:aws:iam::012345678901:role/DummyRole"


StepFunction の実行

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

{
"executionArn": "arn:aws:states:us-east-1:123456789012:execution:HelloWorld:test",
"startDate": 1549812335.58
}


StepFunctin の実行状態の確認

$ aws stepfunctions --endpoint http://localhost:8083 describe-execution --execution-arn arn:aws:states:us-east-1:123456789012:execution:HelloWorld:test

{
"executionArn": "arn:aws:states:us-east-1:123456789012:execution:HelloWorld:test",
"stateMachineArn": "arn:aws:states:us-east-1:123456789012:stateMachine:HelloWorld",
"name": "test",
"status": "SUCCEEDED",
"startDate": 1549812335.58,
"stopDate": 1549812339.711,
"input": "{}",
"output": "{\"statusCode\":200,\"body\":\"{\\\"message\\\":\\\"hello world\\\"}\"}"
}


この手順のハマりどころ

ポイントは、Dockerコンテナの起動時の環境変数 LAMBDA_ENDPOINThost.docker.internal に指定することです。

localhost に指定すると、Docker コンテナからLocalに接続できないので Connection Error になります。

なお、 host.docker.internal というのは Docker コンテナからローカルPCのポートに接続するために用意されたエンドポイントらしいです[4]

。この方法は Docker form Mac/Windows のみ有効のようです。


LAMBDA_ENDPOINTをlocalhostにした場合のエラー

2019-02-10 14:27:56.514: arn:aws:states:us-east-1:123456789012:execution:HelloWorld:test : {"Type":"LambdaFunctionFailed","PreviousEventId":4,"LambdaFunctionFailedEventDetails":{"Error":"Lambda.SdkClientException","Cause":"Unable to execute HTTP request: Connect to localhost:3001 [localhost/127.0.0.1] failed: Connection refused (Connection refused)"}}

2019-02-10 14:27:56.520: arn:aws:states:us-east-1:123456789012:execution:HelloWorld:test : {"Type":"ExecutionFailed","PreviousEventId":5,"ExecutionFailedEventDetails":{"Error":"Lambda.SdkClientException","Cause":"Unable to execute HTTP request: Connect to localhost:3001 [localhost/127.0.0.1] failed: Connection refused (Connection refused)"}}

なお、 LAMBDA_ENDPOINT の設定をせずに起動した場合は The security token included in the request is invalid. という認証系のエラーメッセージとなり、さらに混乱させられました。


LAMBDA_ENDPOINT設定されていない場合のエラー

2019-02-10 14:25:36.380: arn:aws:states:us-east-1:123456789012:execution:HelloWorld:test1 : {"Type":"LambdaFunctionFailed","PreviousEventId":4,"LambdaFunctionFailedEventDetails":{"Error":"Lambda.AWSLambdaException","Cause":"The security token included in the request is invalid. (Service: AWSLambda; Status Code: 403; Error Code: UnrecognizedClientException; Request ID: bb917ab7-8309-447a-a830-28cbedef8aa1)"}}

2019-02-10 14:25:36.381: arn:aws:states:us-east-1:123456789012:execution:HelloWorld:test1 : {"Type":"ExecutionFailed","PreviousEventId":5,"ExecutionFailedEventDetails":{"Error":"Lambda.AWSLambdaException","Cause":"The security token included in the request is invalid. (Service: AWSLambda; Status Code: 403; Error Code: UnrecognizedClientException; Request ID: bb917ab7-8309-447a-a830-28cbedef8aa1)"}}


終わりに

環境変数の設定について、公式チュートリアルには明確な設定内容が書かれてなかったのでけっこうハマりました。。

とにかくこれで、StepFunctionsをローカルから実行することができるようになりました。


参考


  1. Step Functions and Lambda Local

  2. Step Functions Local Configuration Options

  3. DockerHub - amazon/aws-stepfunctions-local

  4. Networking features in Docker Desktop for Mac