はじめに
この記事では、LocalStack を Docker で起動し、AWS サービスをローカル環境で動かす方法を紹介します。
SNS・Lambda・SQS・Parameter Store・Secrets Manager などを、実際の AWS にデプロイせずにローカルで動作確認できます。
この記事で紹介するサンプルプロジェクトは以下のリポジトリで公開しています。
前提として、次のツールが使える状態であることを想定します。
- Go 1.21+
- Docker / Docker Compose
- AWS CLI
-
make、zip
AWS CLI のインストールは次のコマンドで行います。
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip
unzip /tmp/awscliv2.zip -d /tmp/awscli
sudo /tmp/awscli/aws/install
インストール後、認証情報を設定します。LocalStack はダミーの値でも動作しますが、Default output format は必ず json にしてください。他の値にすると AWS CLI のレスポンス解析が崩れる場合があります。
aws configure
# AWS Access Key ID: test
# AWS Secret Access Key: test
# Default region name: ap-northeast-1
# Default output format: json ← 必ず json を指定する
LocalStack とは
LocalStack は AWS サービスをローカルで再現するツールです。
AWS CLI や SDK からは本物の AWS と同じように操作でき、エンドポイントを http://localhost:4566 に向けるだけで切り替えられます。
公式ドキュメントでは localhost.localstack.cloud:4566 も案内されていますが、ローカル利用では localhost:4566 でも問題ありません。
# 本物の AWS への操作
aws sns create-topic --name my-topic
# LocalStack への操作(--endpoint-url を追加するだけ)
aws --endpoint-url=http://localhost:4566 sns create-topic --name my-topic
なぜ LocalStack を使うのか
AWS サービスを使うシステムを開発・テストするとき、次のような場面に出くわします。
- 確認のたびに AWS にデプロイすると、時間とコストがかかる
- SNS → Lambda の連携が正しいか確認するために、デプロイが必要になる
- 開発中に何度も試したいが、AWS の状態が汚れていくのが気になる
LocalStack を使うと、これらの確認をローカルで完結させられます。
開発サイクルが速くなり、AWS へのデプロイは動くことが確認できてからで済みます。
起動方法
Docker Compose で起動します。
services:
localstack:
image: localstack/localstack:3
ports:
- "4566:4566"
environment:
- SERVICES=sns,lambda,sqs,ssm,secretsmanager,logs
- DEFAULT_REGION=ap-northeast-1
docker compose up localstack
SERVICES に使いたいサービスを列挙します。
起動後は http://localhost:4566 がエンドポイントになります。
基本的な操作
SNS トピックを作成する
aws --endpoint-url=http://localhost:4566 sns create-topic \
--name disk-high-alert
Lambda をデプロイする
aws --endpoint-url=http://localhost:4566 lambda create-function \
--function-name slack-notifier \
--runtime nodejs18.x \
--handler index.handler \
--zip-file fileb://function.zip \
--role arn:aws:iam::000000000000:role/lambda-role
IAM ロールの ARN はローカルでは検証されないため、形式さえ合っていれば任意の値で構いません。
SNS から Lambda をサブスクライブする
aws --endpoint-url=http://localhost:4566 sns subscribe \
--topic-arn arn:aws:sns:ap-northeast-1:000000000000:disk-high-alert \
--protocol lambda \
--notification-endpoint arn:aws:lambda:ap-northeast-1:000000000000:function:slack-notifier
SNS にメッセージを Publish する
aws --endpoint-url=http://localhost:4566 sns publish \
--topic-arn arn:aws:sns:ap-northeast-1:000000000000:disk-high-alert \
--message '{"host":"web-01","usage_pct":92.0,"threshold":80.0}'
Publish すると、サブスクライブしている Lambda が起動します。
Parameter Store に値を登録する
aws --endpoint-url=http://localhost:4566 ssm put-parameter \
--name "/disk-monitor/threshold" \
--value "80" \
--type String
Secrets Manager にシークレットを登録する
aws --endpoint-url=http://localhost:4566 secretsmanager create-secret \
--name "disk-alert/slack/webhook" \
--secret-string "https://hooks.slack.com/services/xxx/yyy/zzz"
アプリケーション側の設定
Go や Node.js から LocalStack に接続する場合は、エンドポイントを切り替えます。
Go(AWS SDK v2)
cfg, err := config.LoadDefaultConfig(ctx,
config.WithRegion("ap-northeast-1"),
// ローカル実行時はエンドポイントを LocalStack に向ける
config.WithEndpointResolverWithOptions(
aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{URL: "http://localhost:4566"}, nil
}),
),
)
Node.js(AWS SDK v3)
const { SNSClient } = require("@aws-sdk/client-sns");
const client = new SNSClient({
region: "ap-northeast-1",
// ローカル実行時はエンドポイントを LocalStack に向ける
endpoint: "http://localhost:4566",
});
本番環境では endpoint の指定を外すか、環境変数で切り替えます。
Lambda のログを確認する
LocalStack 上の Lambda が起動したかどうかは、ログで確認できます。
サンプルプロジェクトでは make logs で最新のログストリームを取得できます。
make logs
手動で確認する場合は次のコマンドを使います。
aws --endpoint-url=http://localhost:4566 logs describe-log-groups
aws --endpoint-url=http://localhost:4566 logs describe-log-streams \
--log-group-name /aws/lambda/slack-notifier
aws --endpoint-url=http://localhost:4566 logs get-log-events \
--log-group-name /aws/lambda/slack-notifier \
--log-stream-name <ストリーム名>
注意点
LocalStack は AWS 本番の完全な代替ではありません。
- 無料版(Community)では使えないサービスや機能がある
- IAM の権限評価はローカルでは行われない
- サービスによって再現度に差がある
ローカルでの開発・テスト用途として使い、本番相当の検証は実際の AWS で行います。
「ローカルで動いた=本番でも動く」とはならない点は意識しておく必要があります。
まとめ
LocalStack を使うと、AWS サービスに依存した構成をローカルで確認できます。
- SNS → Lambda の配線が正しいか
- Parameter Store・Secrets Manager からの値取得が動くか
- Publish したメッセージが Lambda まで届くか
これらをデプロイなしで確認できるため、開発サイクルが速くなります。
WireMock と組み合わせると、外部 API のスタブも含めた全フローをローカルで検証できます。
WireMock の使い方については WireMock を Docker で動かして外部 API をスタブする で整理しています。