
lambroll を使って AWS Lambda 関数をデプロイしてる環境で動作確認のために LocalStack にもデプロイしたいという相談があって,検証環境を作る機会があった.結果的に問題なくデプロイできた👌個人環境で検証したことをまとめておく.
今回の構成としては AWS リソースを Terraform でデプロイしつつ,AWS Lambda 関数のコードは GitHub Actions + lambroll でデプロイする.LocalStack に関しては同じく Terraform でデプロイしつつ,AWS Lambda 関数のコードはローカル環境から lambroll deploy コマンドを実行する.

1. Terraform
👾 main.tf
まず,Terraform では IAM Role・AWS Lambda 関数(空っぽ)・Amazon SQS キューをデプロイしておく.AWS Lambda 関数のコードは lambroll でデプロイするため archive_file データソースを使ってダミーコードを設定しておく.
resource "aws_iam_role" "sandbox" { name = "sandbox-role" assume_role_policy = jsonencode( { Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "lambda.amazonaws.com" } } ] } ) } resource "aws_iam_role_policy_attachment" "sqs" { role = aws_iam_role.sandbox.name policy_arn = "arn:aws:iam::aws:policy/AmazonSQSFullAccess" } data "archive_file" "dummy" { type = "zip" source { content = "dummy" filename = "app.py" } output_path = "${path.module}/dummy.zip" } resource "aws_lambda_function" "sandbox" { function_name = "sandbox-function" role = aws_iam_role.sandbox.arn handler = "app.lambda_handler" runtime = "python3.13" filename = data.archive_file.dummy.output_path source_code_hash = data.archive_file.dummy.output_base64sha256 lifecycle { ignore_changes = [ timeout, environment ] } } resource "aws_sqs_queue" "sandbox" { name = "sandbox-queue" }
👾 backend.tf
tfstate は S3 Backend を使って Amazon S3 バケットで管理する.
terraform { backend "s3" { region = "ap-northeast-1" bucket = "xxxxx" key = "terraform.tfstate" use_lockfile = true } }
デプロイ確認
IAM Role・AWS Lambda 関数(空っぽ)・Amazon SQS キューをデプロイできた.

2. lambroll
👾 functions/app.py
今回はサンプルとして AWS Lambda 関数から Amazon SQS キューにメッセージを送信するシンプルな実装にした.
import json import os import uuid import boto3 sqs = boto3.client('sqs') def lambda_handler(event, context): sqs.send_message( QueueUrl=os.environ['QUEUE_URL'], MessageBody=json.dumps( { 'id': str(uuid.uuid4()), }, ), )
👾 functions/function.json
lambroll の function.json では tfstate 記法を使って tfstate から値を取得するようにしている🐑
{ "Architectures": [ "x86_64" ], "Environment": { "Variables": { "QUEUE_URL": "{{ tfstate `aws_sqs_queue.sandbox.url` }}" } }, "EphemeralStorage": { "Size": 512 }, "FunctionName": "sandbox-function", "Handler": "app.lambda_handler", "MemorySize": 128, "Role": "{{ tfstate `aws_iam_role.sandbox.arn` }}", "Runtime": "python3.13", "Timeout": 30 }
👾 .github/workflows/deploy.yml
最後に GitHub Actions + lambroll で AWS Lambda 関数のコードをデプロイする.
name: Deploy Lambda function on: push: branches: - main paths: - ".github/workflows/deploy.yml" - "functions/**" workflow_dispatch: jobs: deploy: runs-on: ubuntu-slim permissions: contents: read id-token: write steps: - name: Checkout repository uses: actions/checkout@v6 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v5 with: role-to-assume: arn:aws:iam::000000000000:role/xxxxx aws-region: ap-northeast-1 - name: Install lambroll uses: fujiwara/lambroll@v1 with: version: v1.4.1 - name: Deploy Lambda run: lambroll deploy --tfstate s3://xxxxx/terraform.tfstate working-directory: functions
デプロイ確認
GitHub Actions 経由で AWS Lambda 関数のコードをデプロイできた.

動作確認
AWS Lambda 関数を実行すると Amazon SQS キューにメッセージを送信できていた👌
$ aws lambda invoke --function-name sandbox-function response.json { "StatusCode": 200, "ExecutedVersion": "$LATEST" }

3. LocalStack
デプロイ
AWS アカウントで動作確認ができたため今度は LocalStack にデプロイする.まずは localstack start -d コマンドで LocalStack を起動しておく.
$ localstack start -d
次に LocalStack Terraform CLI(tflocal コマンド)を使って LocalStack に plan / apply を実行すると問題なくデプロイできる.
$ tflocal plan $ tflocal apply Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
IAM Role・AWS Lambda 関数(空っぽ)・Amazon SQS キューをデプロイできた.

次に lambroll で AWS Lambda 関数のコードを LocalStack にデプロイする.lambroll は --endpoint オプションをサポートしているため LocalStack を指定している👌
しかしこのままだと --tfstate オプションで指定した S3 Backend を参照できず error:failed to read tfstate from s3://xxxxx/terraform.tfstate: operation error S3: GetObject, https response error StatusCode: 403 というエラーが出てしまう🔥今回は lambroll が内部的に依存している tfstate-lookup でサポートされている環境変数 AWS_ENDPOINT_URL_S3 に LocalStack の S3 エンドポイントを指定することで解消した.他の選択肢ある!?
$ export AWS_ENDPOINT_URL_S3=http://s3.localhost.localstack.cloud:4566 $ lambroll deploy --endpoint http://localhost:4566 --tfstate s3://xxxxx/terraform.tfstate
最後は動作確認をする.LocalStack AWS CLI(awslocal コマンド)で AWS Lambda 関数を実行すると Amazon SQS キューにメッセージを送信できていた👌
$ awslocal lambda invoke --function-name sandbox-function response.json { "StatusCode": 200, "ExecutedVersion": "$LATEST" }
