LocalStackでLambdaファンクションをローカルで動かす
MMMバックエンドエンジニアの柳沼です。
文鳥が換羽期なので部屋中に羽が舞ってます。
今回はAtlassianが開発しているLocalStackを使って、Lambdaファンクションをローカルに閉じて動かしてみます。
LocalStackチュートリアル
まずは、LocalStackを使ってみます。
pipでインストールすることもできるのですが、
dockerイメージが公開されているため、そちらを使っていきます。
今回は公式のdocker-compose.ymlを使って、以下のように実行しました。
$ wget https://raw.githubusercontent.com/localstack/localstack/master/docker-compose.yml
$ docker-compose up -d
しばらくするとこのように、LocalStackのコンテナが上がってきます。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ca98225f6bba localstack/localstack "/usr/bin/supervisor…" 13 minutes ago Up 13 minutes 0.0.0.0:4567-4583->4567-4583/tcp, 0.0.0.0:8080->8080/tcp sam_localstack_1
ポートが空くのを確認しましょう。
$ netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp6 0 0 :::8080 :::* LISTEN
tcp6 0 0 :::4567 :::* LISTEN
tcp6 0 0 :::4568 :::* LISTEN
tcp6 0 0 :::4569 :::* LISTEN
tcp6 0 0 :::4570 :::* LISTEN
tcp6 0 0 :::4571 :::* LISTEN
tcp6 0 0 :::4572 :::* LISTEN
tcp6 0 0 :::4573 :::* LISTEN
tcp6 0 0 :::4574 :::* LISTEN
tcp6 0 0 :::4575 :::* LISTEN
tcp6 0 0 :::4576 :::* LISTEN
tcp6 0 0 :::4577 :::* LISTEN
tcp6 0 0 :::4578 :::* LISTEN
tcp6 0 0 :::4579 :::* LISTEN
tcp6 0 0 :::4580 :::* LISTEN
tcp6 0 0 :::4581 :::* LISTEN
tcp6 0 0 :::4582 :::* LISTEN
tcp6 0 0 :::4583 :::* LISTEN
(以下略)
8080番及び4567~4583が空くと思います。
この状態で localhost:8080
にアクセスしてみましょう。
このようにコンソールにアクセスできます。
8080番以外のポートはなにかというと、AWSの各サービスを示しています。
READMEに説明があります。
例えば、S3を利用してみましょう。
READMEによればS3のポートは4572なので、以下のようにバケットとオブジェクトを作ってみます。
$ aws --endpoint-url=http://localhost:4572 s3api create-bucket --bucket sam_test
$ echo "Hello world" > s3.txt
$ aws --endpoint-url=http://localhost:4572 s3 cp ./s3.txt s3://sam_test
これで先程のコンソールをリロードしてみると、バケットができています!!
これだけでも、ローカルでS3バケットをモックできるため、開発中に実際のS3バケットを見に行く必要がなくなります。便利。
今回は、LocalStack上のLambdaのエンドポイントに関数を作成し、実行します。
Lambdaファンクション作成
それでは、Lambdaファンクションを作ります。
aws cli
の lambda create-function
すればいいのですが、普通に作っただけではLocalStackのエンドポイントに作れないので、以下のような作り方をします。
まずはスクリプトを作成。
$ vi lambda.py
def lambda_handler(event, context):
print(event)
return 'LocalStack TEST'
zip化します。
$ zip lambda.zip lambda.py
そして、create-functionします。
$ aws --endpoint-url=http://localhost:4574 --region us-east-1 --profile localstack lambda create-function --function-name=f1 --runtime=python2.7 --role=r1 --handler=lambda.lambda_handler --zip-file fileb://lambda.zip
最大のポイントは --endpoint-url=http://localhost:4574
です。これでLocalStackに作ってくれます。
うまくできれば、以下のように返ってきます。
{
"TracingConfig": {},
"FunctionName": "f1",
"VpcConfig": {
"SubnetIds": [
null
],
"SecurityGroupIds": [
null
]
},
"FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:f1",
"Environment": {
"Variables": {},
"Error": {}
},
"Handler": "lambda.lambda_handler",
"Role": "r1",
"Runtime": "python2.7"
}
コンソールをリロードすれば、ファンクションができていると思います。
ちなみに、右の Show code
からコードを見ることもできます。便利。
実行は以下のようにします。
$ aws lambda --endpoint-url=http://localhost:4574 invoke --function-name f1 --payload '{"key1":"value1"}' result.log
{
"StatusCode": 200
}
200が返ると思います。
ログを見てみます。
$ cat result.log
LocalStack TEST
バッチリですね!!
まとめ
Lambdaファンクション作成 → 実行をローカルで完結させることができ、テストコードも書きやすくなるかと思います。インターネットに出る必要もなく、AWSリソースとしてのコストも考慮しなくていいので、開発時には非常に有用かと思います。
今回は書いていませんが、aws-sam-localと組み合わせることでより実際の環境に近づけることも可能です。
なお、以下のぺージでMMMのAWS Lambdaへの取り組みをご紹介しています。ぜひ合わせてご覧ください。