LocalStackを使ったAWS Lambdaデバッグ
LocalStackとは?
LocalStackは、パーソナルコンピューターまたはサーバー上に疑似されたクラウド環境でアプリケーションを展開して実行するために使われるオープンソース ソフトウェア開発ツールです。 Amazon S3、AWS Lambda、DynamoDBなど流行っているクラウドサービスのレプリカを提供します。これにより、本物のクラウド環境に接続することなく、アプリケーションの開発、テスト、デバッグが可能になります。
インストール
LocalStackインストール
以下のマニュアルを参照してLocalStackをインストールします。
https://docs.localstack.cloud/getting-started/installation/
Dockerインストール
以下のマニュアルを参照してDockerをインストールします。
https://docs.docker.com/engine/install/
AWS CLIインストール
以下のマニュアルを参照してAWS CLIをインストールして、ロカール環境のプロフィールを設定します。
https://docs.localstack.cloud/user-guide/integrations/aws-cli/#aws-cli
LocalStack設定
docker-compose.yml作成
Docker-Composeの設定を使ってLocalStackを起動します。docker-compose.ymlというファイルを新たに作成し、以下のように設定します。
version: "3.8"
services:
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}" # Name of the container to be used
image: localstack/localstack:latest # Docker image for LocalStack, latest version
ports:
- "127.0.0.1:4566:4566" # Port for accessing LocalStack Gateway from the local machine
- "127.0.0.1:4510-4559:4510-4559" # Port range for external services
environment:
- DEBUG=1 # Enable Debug mode in LocalStack
- LAMBDA_REMOTE_DOCKER=0 # Turn off remote Docker usage for Lambda
- LAMBDA_DOCKER_FLAGS=-e NODE_OPTIONS=--inspect-brk=0.0.0.0:9229 -p 9229:9229 # Exposes port 9229 for debugging the Lambda handler code.
- LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR-} # Lambda execution type (if defined)
- DOCKER_HOST=unix:///var/run/docker.sock # Link to Docker via Docker socket
volumes:
- "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" # Mount point for LocalStack data directory
- "/var/run/docker.sock:/var/run/docker.sock" # Mount Docker socket to access Docker from the LocalStack container
Dockerを使ったLocalStack起動
以下のコマンドを実行してLocalStackを起動します。
docker compose up -d
上記のコマンドを実行した後、Docker ContainerがRunningになっていることを確認できます。
そして、LocalStackの起動が完了します。
Lambda関数デバッグ設定
launch.json作成
.vscode/launch.jsonファイルを作成して、以下のように設定します。
{ "version": "0.2.0", "configurations": [ { "address": "127.0.0.1", "localRoot": "${workspaceFolder}", "name": "Attach to Remote Node.js", "port": 9229, "remoteRoot": "/var/task/", "request": "attach", "type": "node", "preLaunchTask": "Wait Remote Debugger Server" }, ] }
tasks.json作成
.vscode/tasks.jsonファイルを作成して、以下のように設定します。
{ "version": "2.0.0", "tasks": [ { "label": "Wait Remote Debugger Server", "type": "shell", "command": "while [[ -z $(docker ps | grep :9229) ]]; do sleep 1; done; sleep 1;" } ] }
注意:上記の実装はLinuxやmacOSでしか動作できません。Windowsの場合、以下のように実装する必要があります。
.vscode/tasks.jsonファイルを作成します。
{ "version": "2.0.0", "tasks": [ { "label": "Wait Remote Debugger Server", "type": "shell", "command": "powershell", "args": [ ".\\.vscode\\wait-debugger.ps1" ] } ] }
while (-not (docker ps | Select-String ":9229")) { Start-Sleep -Seconds 1 } Start-Sleep -Seconds 1
function.ts作成
以下の例では、デバッグのために使われる、Node.jsとTypeScriptで開発したLambda関数が含まれたfunction.tsファイルを作成します。
export const handler = async (event: any) => { const response = { statusCode: 200, body: "hello word", }; return response; };
LocalStackでのLambda関数作成
以下のコマンドを実行して、Lambda関数をLocalStackで生成します。
aws --endpoint-url=http://localhost:4566 lambda create-function \ --function-name localstack-lambda-function \ --code S3Bucket="hot-reload",S3Key="$(pwd)/" \ --handler function.handler \ --runtime nodejs18.x \ --timeout 120 \ --role arn:aws:iam::000000000000:role/lambda-role
上記のコマンドを実行した後、Lambda関数がLocalStackで生成されたことを確認できます。
Lambda関数のデバッグ
VS Codeでは、ソースをデバッグしたいところでブレークポイントを配置し、F5キーを押して実行することでデバッグを行うことができます。
以下のコマンドでLambda関数を実行します。
aws --endpoint-url=http://localhost:4566 lambda invoke \ --function-name localstack-lambda-function lambda.log \ --cli-binary-format raw-in-base64-out \ --payload '{"hello":"world"}'
上記のコマンドを実行した後、デバッグが完了します。
Amazon S3を使ったLambda 関数をデバッグしてのファイルアップロード時AWS Lambdaトリガー
Amazon S3でのバケット作成
以下のコマンドを使ってAmazon S3でバケットを作成します。
aws s3api create-bucket --bucket local-stack-bucket --create-bucket-configuration LocationConstraint=ap-northeast-1 --endpoint-url=http://localhost:4566
そのコマンドの中で
・local-stack-bucket:バケットの名前
Amazon S3トリガーのLambda関数への設定
以下のコマンドを使って、ファイルアップロード時にLambda関数をAmazon S3へトリガーします。
aws --endpoint-url=http://localhost:4566 s3api put-bucket-notification-configuration \ --bucket local-stack-bucket \ --notification-configuration '{ "LambdaFunctionConfigurations": [ { "Id": "1", "LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:000000000000:function:localstack-lambda-function", "Events": ["s3:ObjectCreated:*"] } ] }'
そのコマンドの中で
・local-stack-bucket:設定するバケットの名前
・LambdaFunctionArn:トリガーするLambda関数のArn
・Events:Lambda関数トリガーのためのAmazon S3のイベント
Lambda関数のデバッグ進行
VS Codeでは、ソースをデバッグしたいところでブレークポイントを配置し、F5キーを押して実行することでデバッグを行うことができます。
その後、ファイルをLocalStackのクラウド上のAmazon S3バケットにアップロードします。
ファイルをアップロードした後、デバッグが完了します。
LocalStackのデメリット
AWSサービスへのサポート制限:LocalStackは、S3、DynamoDB、Lambda、SQSといった重要なサービスのシミュレーションを提供します。しかし、全てのAWSサービスをサポートする訳ではありません。一部のサービスは利用できないか、一部機能する場合があります。若しアプリケーションがサポートされていないサービスに依存する場合、面倒になります。
機能不足:LocalStackはサービスを擬似しますが、全て機能する訳ではありません。設定オプションが制限されるので、ローカル開発環境とAWS上の実際環境との同一性が低くなります。
拡張性制限:LocalStackは、AWS環境と違って、積極的に拡張できるようにデザインされません。大規模なプロジェクトの場合、ローカル環境で開発しテストを実施することはAWSで行う時の現状と合わないこともあります。
遅延:LocalStackは、AWSサービスを擬似して複製したので実際のサービス使用に比べて遅延が発生する可能性があります。これにより、開発とテストが遅くなり、生産性が低下します。
スロー更新:LocalStackは、AWS サービスの新しいバージョンに伴い更新はすぐにしない可能性があります。これにより、AWSの新しい機能を使う時やAWS APIに変更があった時に、非同期が発生する可能性があります。
結論
LocalStackを使うことによりLambda関数や他のAWSサービスをローカル環境で効果的に開発しデバッグを行うことができます。本物のAWSに展開する前に、適切に統合して正常に動作することを確保でき、開発中に、AWSアカウントへの影響を削減し、手間やコストを削減することもできます。