はじめに
AWSのサービスをローカル環境で利用できる LocalStack を紹介したいと思います。
S3、Lambda、DynamoDB、SQSなど、AWSサービスをローカル環境で疑似的に利用できて、料金などを気にすることなくテストやコードの動作確認を行うことが出来ます。
目次
LocalStackとは
LocalStackとは、ローカル環境でAWSのサービスをエミュレートするフレームワークです。
pipやdockerを用いて簡単に環境構築が可能です。
LocalStackは無料版と有料版があり、無料版は利用できるAWSサービスに制限があったり、データが永続化できないといった違いがあります。
今回は LocalStack をインストールして S3,SQS を使ってみました。
インストールと起動
- awscli-localインストール
AWS CLI でも LocalStack 環境は操作できるのですが、毎回エンドポイントを指定する必要があったり少々手間なので、AWS CLIをLocalStack向けにラップした awslocal コマンドをインストールして使いました。
1 |
pip3 install awscli-local |
awslocal の場合
awslocal s3 mb s3://test-bucket1
AWS CLI の場合
aws s3 mb s3://test-bucket2 --endpoint-url=http://localhost:4566
- GitHub から LocalStack 環境をクローン
1 |
git clone https://github.com/localstack/localstack.git |
- docker-compose.ymlの作成
設定は公式ドキュメントを参考にしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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: # LocalStack configuration: https://docs.localstack.cloud/references/configuration/ - DEBUG=${DEBUG:-0} - PERSISTENCE=1 volumes: - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" - "/var/run/docker.sock:/var/run/docker.sock"<br> |
- docker-composeで起動します
1 2 3 4 |
$ sudo docker-compose up -d [+] Running 2/2 ⠿ Network localstack_default Created 0.1s ⠿ Container localstack-main Started 1.2s |
- AWSサービスの確認
1 |
$ curl -s "http://localhost:4566/_localstack/health" | jq . |
available は使用可能な状態
running は使用中
これで、LocalStack の使用できる環境準備が出来ました。
S3 バケットにファイルアップロードしてみた
バケットを作成して、ファイルをアップロードしてみます。
- バケットの作成
1 2 |
$ awslocal s3 mb s3://test-bucket1 make_bucket: test-bucket1 |
- ファイルアップロードとバケット確認
1 2 3 4 |
$ awslocal s3 cp test.txt s3://test-bucket1/ upload: ./test.txt to s3://test-bucket1/test.txt $ awslocal s3 ls s3://test-bucket1/ 2024-08-14 11:01:37 5 test.txt |
SQS キューにメッセージを送信してみた
C#のサンプルコードで、作成したキューにメッセージの送受信をしてみます。
- キューの作成
1 2 3 4 |
$ awslocal sqs create-queue --queue-name my-local-test-queue { "QueueUrl": "http://sqs.ap-northeast-1.localhost.localstack.cloud:4566/000000000000/my-local-test-queue" } |
- キューの確認
1 2 3 4 5 6 7 |
$ awslocal sqs list-queues { "QueueUrls": [ "http://sqs.ap-northeast-1.localhost.localstack.cloud:4566/000000000000/my-local-queue", "http://sqs.ap-northeast-1.localhost.localstack.cloud:4566/000000000000/my-local-test-queue" ] } |
- キューにメッセージの送信と取得するサンプルコード(C#)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
using Amazon.Lambda.Core; using Amazon.SQS; using Amazon.SQS.Model; using Sample.App.Setting; // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class. [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] namespace LocalStack_Access { class Program { private const string LocalQueueUrl = "http://localhost:4566/000000000000/local-test-queue"; static async Task Main(string[] args) { var getAppSetting = new GetAppSetting(); var appsettings = getAppSetting.GetSettings(); if (appsettings != null) { // 送信するメッセージ string messageBody = "Hello from C# to LocalStack SQS!"; // SQSメッセージ送信 await SQS_message_putAsync(messageBody); // SQSメッセージを取得 await SQS_message_getAsync(); } else { Console.WriteLine("Failed to load application settings."); } } private static IAmazonSQS GetSQSClient() { if (AWSConfig.UseLocalStack) { return new AmazonSQSClient(AWSConfig.Credentials, new AmazonSQSConfig { ServiceURL = AWSConfig.LocalStackEndpoint, AuthenticationRegion = AWSConfig.Region.SystemName }); } return new AmazonSQSClient(AWSConfig.Credentials, AWSConfig.Region); } public static async Task SQS_message_putAsync(string messageBody) { using var sqsClient = GetSQSClient(); string queueUrl = LocalQueueUrl; try { // メッセージの送信 var sendMessageRequest = new SendMessageRequest { QueueUrl = queueUrl, MessageBody = messageBody }; var response = await sqsClient.SendMessageAsync(sendMessageRequest); Console.WriteLine($"Message sent. MessageId: {response.MessageId}"); } catch (Exception ex) { Console.WriteLine($"Error sending message: {ex.Message}"); } } public static async Task SQS_message_getAsync() { using var sqsClient = GetSQSClient(); string queueUrl = LocalQueueUrl; try { // メッセージの取得 var receiveMessageRequest = new ReceiveMessageRequest { QueueUrl = queueUrl, }; var response = await sqsClient.ReceiveMessageAsync(receiveMessageRequest); if (response.Messages.Count > 0) { Console.WriteLine($"Received {response.Messages.Count} message(s):"); foreach (var message in response.Messages) { Console.WriteLine($"Message Body: {message.Body}"); Console.WriteLine($"Message ID: {message.MessageId}"); Console.WriteLine("--------------------"); // メッセージを処理した後、キューから削除 await sqsClient.DeleteMessageAsync(queueUrl, message.ReceiptHandle); } } else { Console.WriteLine("No messages received."); } } catch (Exception ex) { Console.WriteLine($"Error sending message: {ex.Message}"); } } } }じ |
送信したメッセージと取得したメッセージを確認(コマンドで確認)
1 2 3 4 5 6 7 8 9 10 11 |
$ awslocal sqs receive-message --queue-url http://localhost:4566/000000000000/local-test-queue { "Messages": [ { "MessageId": "d6c64c56-54f1-40a1-8cae-d90db7085f08", "ReceiptHandle": "YjQwZTI2ZmEtZmFkZC00ZTE1LWIyNGUtMzczNTU2M2IyOTExIGFybjphd3M6c3FzOmFwLW5vcnRoZWFzdC0xOjAwMDAwMDAwMDAwMDpsb2NhbC10ZXN0LXF1ZXVlIGQ2YzY0YzU2LTU0ZjEtNDBhMS04Y2FlLWQ5MGRiNzA4NWYwOCAxNzIzNjI0NTcxLjEzNzYwODg=", "MD5OfBody": "7e5a8f93ee5af7c0957d644fb36903aa", "Body": "Hello from C# to LocalStack SQS!" } ] } |
vscodeでコード実行時のコンソールのログを確認
データの永続化
無料版ではデータの永続化ができないので、ローカル環境で起動のたびに作成したリソースやデータが消えてしまいます。
起動のたびにリソースを作成したり、データを入れたりするのは面倒なので、初期化用のスクリプトを準備して、Dockerコンテナ起動時に自動で初期化するようにしました。
スクリプトは、/etc/localstack/init/ready.d
に配置します。
init-aws.sh
1 2 3 4 5 6 7 8 9 |
#!/bin/bash # デフォルトリージョンを東京(ap-northeast-1)に設定 export AWS_DEFAULT_REGION=ap-northeast-1 # S3バケットの作成 awslocal s3 mb s3://s3bucket-yoshi-test # SQSキューの作成 awslocal sqs create-queue --region ap-northeast-1 --queue-name yoshi-test-queue |
docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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: # LocalStack configuration: https://docs.localstack.cloud/references/configuration/ - DEBUG=${DEBUG:-0} - PERSISTENCE=1 volumes: - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" - "/var/run/docker.sock:/var/run/docker.sock" + - "./init-aws.sh:/etc/localstack/init/ready.d/init-aws.sh" # 起動時にリソース作成のスクリプトを実行する |
まとめ
LocalStackを使うことで、AWS環境を自分のローカルで自由に使うことが出来ました。
無料版なので制限はありますが、環境構築前に先行してコードの開発が行えたり、ローカル環境なので料金も気にすることなく、自由に使うことは出来ると感じました。
投稿者プロフィール
-
2023/1にスカイアーチネットワークスにJoin
AWSを日々勉強中
最新の投稿
- AWS2024年8月20日LocalStackをつかってローカル環境でAWSサービスにアクセスしてみた
- AWS2024年4月4日AWS NeptuneにLambdaからアクセスしてみた
- セキュリティ2024年3月4日Amazon GuardDutyについてまとめてみました
- AWS2023年12月4日Amazon Redshift Streaming Ingestion をやってみた