ユニファ開発者ブログ

ユニファ株式会社プロダクトデベロップメント本部メンバーによるブログです。

Local Development with LocalStack

こんにちは。プロダクトエンジニアリング部の杉本です。

この記事は、UniFaアドベントカレンダー2020 の16日目の記事になります。
(私事ですが、2020年6月にユニファにjoinして半年がたち、初めてのブログ投稿です!)

皆さんは、AWSマネージドサービスに依存する機能を開発する場合、ローカルでどのように動作確認をされていますか?

  • 実際のAWS環境にローカルから接続する
  • レスポンスをスタブ化する*1
  • ローカルはそこそこに、とりあえず検証環境にデプロイして確認する

他にも様々あり、プロジェクトのフェーズや事情によっていずれも選択肢になりえると思います。
でもそれに相まって、多少なりともかかるコスト誤接続や誤操作によるリスク動作確認不十分な品質 など課題もでてきますよね。。。

今回は、そんなときにオススメな LocalStackを紹介したいと思います。

LocalStackとは

github.com

LocalStack provides an easy-to-use test/mocking framework for developing Cloud applications.

LocalStackは、ローカル環境においてAWSの各マネージドサービスと同じ機能、APIを提供してくれます。

AWSのモックサービスにはmotoElasticMQなど有名なものが多くありますね。
LocalStackも内部的にはこれらを利用しています。

導入も容易で

  • pip によるインストール
  • Dockerイメージの利用*2

のいずれかで可能で、READMEのOverviewにある通りCommunity版だけでも相当数のマネージドサービスをエミュレートすることができます。

ちなみに、GCPやAzureにはLocalStackほどのツールは(調べた限りでは)ありませんが、特にストレージ、メッセージングサービスについては公式のエミュレータが存在します。

cloud.google.com docs.microsoft.com

LocalStackの使い方

使い方、といってもLocalStackはエンドポイントを指定してCLIなどでリソースや設定を作成していくだけです。
なので「使ってみた」というのは割愛しますが、導入時にはいくつかポイントがあります。

LocalStackは、基本的に設定ファイルのようなものがなく、環境変数に諸々を設定していくことになります。

version: '2'
services:
  ...
  localstack:
    image: localstack/localstack
    ports:
      - "4566:4566"
    environment:
      DATA_DIR: /tmp/localstack
      DEFAULT_REGION: ap-northeast-1 # default: us-east-1
      HOSTNAME_EXTERNAL: localstack
      SERVICES: sns,sqs
    volumes:
      - ./localstack/init_scripts:/docker-entrypoint-initaws.d
      - localstack_tmp:/tmp/localstack
  ...

あくまで一部なので、詳細や他の設定はConfigurationsをご覧ください

PORTS

"LocalStack"で検索すると、サービスごとのポート一覧をまとめている記事がいくつかヒットします。

LocalStackは過去には1サービスにつき1つのポートがバインドされていましたが、しばらくの併用期間の後にv0.11.5からは4566番ポートのみを介して提供するようになっています。(Pro版のWebUIのみ8080

サービスごとには<SERVICE>_PORT_EXTERNALでポートを指定することも可能です。

DATA_DIR

永続化データを保存するディレクトリを指定することができます。
本記事の執筆時点では、下記のサービスのみ永続化が可能です。

  • Kinesis
  • DynamoDB
  • Elasticsearch
  • S3
  • Secretsmanager
  • SSM
  • SQS
  • SNS

HOSTNAME_EXTERNAL

SQSのQueueURLなどリソース情報にホスト名が含まれる場合、デフォルトではホスト名はlocalhostになります。
しかしアプリケーションのコンテナLocalStackのコンテナへリクエストするときのホスト名は、前述のdocker-compose.ymlではlocalstackになるため、QueueURLが見つからずエラーが発生することになります。

この場合はあらかじめHOSTNAME_EXTERNALに、docker-compose.ymlのサービス名を設定し、外部公開用のホスト名を上書いておくことで解決することができます。

# aws sqs list-queues --endpoint-url http://localhost:4566

# default で作成した場合のqueue_url
http://localhost:4566/000000000000/localstack_queue

# HOSTNAME_EXTERNAL=localstack で作成した場合のqueue_url
http://localstack:4566/000000000000/localstack_queue

SERVICES

LocalStackで起動するサービスはSERVICESで指定します。

SERVICES: s3,sns,sqs

ものによってはグルーピングされていて(管理のうえで便利かはわかりませんが)面白いところです。

localstack/bootstrap.py at master · localstack/localstack · GitHub

# composites define an abstract name like "serverless" that maps to a set of services
API_COMPOSITES = {
    'serverless': ['cloudformation', 'cloudwatch', 'iam', 'sts', 'lambda', 'dynamodb', 'apigateway', 's3'],
    'cognito': ['cognito-idp', 'cognito-identity']
}

LocalStackをより便利に使うために

リソースの初期化

S3バケットやSQSキューなど、あらかじめ必要と分かっているリソースを、開発メンバーそれぞれが毎回作成するのはとても面倒ですね。

LocalStackでは/docker-entrypoint-initaws.dディレクトリ配下にスクリプト*.shを配置すると、サービス起動後にこれを実行してくれます。
(ディレクトリパスはINIT_SCRIPTS_PATHで変更可)
さらにLocalStackにはawslocalというaws cliをラップしたツールがあり、これがまた便利です。

↓は例としてSQSのキュー&デッドレターキューを作成するスクリプトです。

#!/bin/sh
awslocal sqs create-queue --queue-name localstack_dead_letter_queue
awslocal sqs create-queue --queue-name localstack_queue \
  --attributes '{"RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:ap-northeast-1:000000000000:localstack_dead_letter_queue\",\"maxReceiveCount\":3}"}'

LocalStackの起動時に作成されるので、開発メンバーそれぞれがリソース有無を意識する必要がないのは、非常に便利ですね!

サービスのヘルスチェック

LocalStackは、LocalStackそのものが立ち上がったあとに SERVICES で指定したサービスを順次起動していきます。
そのため、例えばdocker-composeを使用した場合に depends_on で指定しても、サーバープロセス起動とほぼ同時にAWSに繋ぎにいくようなサービスである場合は、Connection Errorが出ることになります。

ローカルであればさほど問題ではありませんが「LocalStackを自動テストに組み込みたい」など要望によっては厳密にしたいことがあります。
そんなときは、LocalStackにはヘルスチェック用のエンドポイントが用意されているので、これを活用することができます。

$ curl -s http://localhost:4566/health | jq
{
  "services": {
    "sns": "running",
    "sqs": "running"
  }
}

Pro版を活用する

LocalStackはCommutiny版でも十分に便利ですが、Pro版*3ではWeb UI(Community版は aws cli での操作)に加えてElastiCache、S3 Selectなどより多くのサービスを使用することができるようになります。

LocalStack comes in two flavors - as a free, open source Base Edition, and as a Pro Edition with extended features and support. See the table below for a comparison. If you need support for large organizations, please contact us for the Enterprise Edition.

プロジェクトによって「何を、どこまで、確認したいのか」は様々ですし、LocalStack上に必要なリソースや設定を作成していく手間もあるので、あとは諸々とご相談ですね。

最後に

LocalStackは無料かつローカルで使用できるので

  • Terraformのお試し実行環境
  • AWSを学び始めた方の練習環境

としても有用です。上手く活用して、開発の品質も効率も高めていきたいですね!

ユニファでは、継続的にサービスを改善していきたいエンジニア、デザイナー、プロダクトマネージャーを積極採用中です!

unifa-e.com

最後までお読みいただき、ありがとうございました!