LocalStackを使ったAWS Lambdaデバッグ

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
また、以下のマニュアルを参照してLocalStack の他の設定を追加することができます。

Dockerを使ったLocalStack起動

以下のコマンドを実行してLocalStackを起動します。

docker compose up -d

上記のコマンドを実行した後、Docker ContainerがRunningになっていることを確認できます。

そして、LocalStackの起動が完了します。

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"
      ]
    }
  ]
}
.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アカウントへの影響を削減し、手間やコストを削減することもできます。

参考元

https://docs.localstack.cloud/