AWS

LocalStackでLambdaファンクションをローカルで動かす

MMM Corporation
mmmuser

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 clilambda 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への取り組みをご紹介しています。ぜひ合わせてご覧ください。

サーバーレスアーキテクチャ(AWS Lambda)

AUTHOR
デロイト トーマツ ウェブサービス株式会社(DWS)
デロイト トーマツ ウェブサービス株式会社(DWS)
デロイト トーマツ ウェブサービス株式会社はアマゾン ウェブ サービス(AWS)に 専門性や実績を認定された公式パートナーです。
記事URLをコピーしました