ローカルスタックはコンテナで動作するクラウドサービスエミュレータで、awscliやboto3からAWSのように操作することができます。
バックエンドでboto3を利用するときに、いちいちモックの実装を組まなくていいのでテストが楽になります。
■ 起動
Dockerで起動する方法
docker run \
--rm -it \
-p 4566:4566 \
-p 4510-4559:4510-4559 \
localstack/localstack
Docker Composeで起動する方法
version: "3.8"
services:
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME-localstack-main}"
image: localstack/localstack
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
- "127.0.0.1:4510-4559:4510-4559" # external services port range
environment:
- DEBUG=1 # デバッグレベルのログを出力する
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- "${LOCALSTACK_VOLUME_DIR:-./localstack-volume}:/var/lib/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
docker-compose up -d
■ 操作
awscli
--endpoint-url
オプションに http://localhost:4566
を設定するとローカルスタックにリクエストするようになります。
LOCALSTACK_ENDPOINT_URL=http://localhost:4566
# トピック作成
aws \
--endpoint-url=$LOCALSTACK_ENDPOINT_URL \
--region ap-northeast-1 \
sns create-topic \
--name sample-topic-01
# パブリッシュ
aws \
--endpoint-url=$LOCALSTACK_ENDPOINT_URL \
--region ap-northeast-1 \
sns publish \
--message "hello" \
--topic-arn "arn:aws:sns:ap-northeast-1:000000000000:sample-topic-01"
boto3
boto3でローカルスタックを操作する場合も同様に、 endpoint_url
に http://localhost:4566
を設定します。
>>> import boto3
>>> client = boto3.client("sns", region_name="ap-northeast-1", endpoint_url="http://localhost:4566")
# トピック作成
>>> client.create_topic(Name="sample-topic-02")
{'TopicArn': 'arn:aws:sns:ap-northeast-1:000000000000:sample', 'ResponseMetadata': {'RequestId': '846c86f6-7998-4b51-ae56-a69156151579', 'HTTPStatusCode': 200, 'HTTPHeaders': {'content-type': 'text/xml', 'content-length': '333', 'connection': 'close', 'date': 'Wed, 29 Nov 2023 08:50:29 GMT', 'server': 'hypercorn-h11'}, 'RetryAttempts': 0}}
# パブリッシュ
>>> client.publish(TopicArn="arn:aws:sns:ap-northeast-1:000000000000:sample-topic-02", Message="hello")
{'MessageId': 'bec5715a-45f4-4651-b7ff-711960388b90', 'ResponseMetadata': {'RequestId': '82d4e133-fef3-4ecd-a05c-9325892b755c', 'HTTPStatusCode': 200, 'HTTPHeaders': {'content-type': 'text/xml', 'content-length': '309', 'connection': 'close', 'date': 'Wed, 29 Nov 2023 08:51:15 GMT', 'server': 'hypercorn-h11'}, 'RetryAttempts': 0}}
awscli-local
awslocalはローカルスタックで利用するためのawscliの薄いラッパーです。
sudo pip install awscli-local
# トピック作成
awslocal \
--region ap-northeast-1 \
sns create-topic \
--name sample-topic-03
# パブリッシュ
awslocal \
--region ap-northeast-1 \
sns publish \
--message "hello" \
--topic-arn "arn:aws:sns:ap-northeast-1:000000000000:sample-topic-03"
■ 初期化
Initialization Hooks | LocalStack
コンテナ起動時に自動的に指定のリソースを作成するための方法です。
/etc/localstack/init/ready.d/
配下に実行可能なpythonスクリプトもしくはshellスクリプトを配置すると、コンテナ起動時に実行されます。
/etc/localstack/init/ready.d/
配下に配置する 初期化スクリプトを作成します。
touch init-aws.sh
chmod 755 init-aws.sh
vim init-aws.sh
#!/bin/bash
awslocal sns create-topic \
--region ap-northeast-1 \
--name sample-topic
docker-compose.ymlを作成します。
vim docker-compose.yml
version: "3.8"
services:
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME-localstack-main}"
image: localstack/localstack
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
- "127.0.0.1:4510-4559:4510-4559" # external services port range
environment:
- DEBUG=1 # デバッグレベルのログを出力する
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- "${LOCALSTACK_VOLUME_DIR:-./localstack-volume}:/var/lib/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
- ./init-aws.sh:/etc/localstack/init/ready.d/init-aws.sh # 初期化スクリプトをマウント
ローカルスタックを起動して、初期化スクリプト通りにsnsトピックが作成されているかを確認します。
# localstackを起動
docker-compose up -d
# トピックにメッセージを送信
LOCALSTACK_ENDPOINT_URL=http://localhost:4566
awslocal \
--region ap-northeast-1 \
sns publish \
--message "hello" \
--topic-arn "arn:aws:sns:ap-northeast-1:000000000000:sample-topic"
# ログの閲覧
docker-compose logs
初期化スクリプトの実行ステータスは下記のAPIでチェックできます。
$ curl -s localhost:4566/_localstack/init | jq .
{
"completed": {
"BOOT": false,
"START": true,
"READY": true,
"SHUTDOWN": false
},
"scripts": [
{
"stage": "BOOT",
"name": "booting.sh",
"state": "UNKNOWN"
},
{
"stage": "READY",
"name": "pre_seed.py",
"state": "SUCCESSFUL"
}
]
}