Serverless OfflineがOOMで落ちるので、dynamo-localをDockerにする
serverless frameworkをローカルの環境で動作させるにはserverleff-offlineのプラグインを利用します。
serverless-offlineのプラグインは使用していると、メモリを使い切ってOOMで落ちてしまうという残念な特徴があります。Githubのissueにも上がっています。
基本的にserverlessはステートレスの処理なので、落ちても問題がないことがほとんどですが、1点だけ重要になる点があります。
永続層への書き込み、今回の場合はDynamoDBへの書き込みです。
serverless frameworkのプラグインとして、serverless-dynamodb-localがあり、これを利用することで、dynamoDBをローカルで起動することができます。
serverless frameworkのプラグインとして動かすということは、serverless frameworkの子プロセスとして起動するということ。つまり、serverless frameworkが上述のOOMで落ちてしまうと、子プロセスも一緒に終了してしまいます。
そのため、テストのためのデータをDynamoDBに書き込みしている途中に落ちてしまって、何度も同じ処理をやり直すということが発生していました。
serverless frameworkが停止しても、データを保持しておく方法は2点あります。dynamodb-localのデータをファイルに保存する(基本はメモリに保存している)か、dynamodb-locaを別のプロセスとして起動するかです。
データをファイルに保存するのは直感的に反する感じがしたので、別のプロセスとして起動する方法を検討しました。
起動などに手間をかけたくないので、dynamodb-localはdockerで起動できるようにします。
serverless-dynamodb-localでは内部的にamazonが提供しているjarファイルを実行しています。
dynamodb-localはありがたいことにdocker hubにコンテナが登録されています。
説明を見るとオプションは特に必要なくportの指定だけで動きそうに見えます。
docker run -p 8000:8000 amazon/dynamodb-local
serverless-dynamodb-localのオプションにnoStart: true
を入れてserverless offline
を起動します。
dynamodb:
start:
port: 8000
+ noStart: true
inMemory: true
migrate: true
seed: true
ちゃんと起動しているように見えるのですが、serverless offlineとdynamodbがつながっていないように見えます。
そこで、調べてみたところ以下のissueが出てきました。
デフォルトのdockerではオプションが足りないため起動しないとのこと。そのため、issueにあるものをそのまま利用して、docker-composeを使ってdynamodb-localを起動したところ、意図した通りの挙動になりました。
dynamodb:
image: 'amazon/dynamodb-local'
ports:
- '8000:8000'
command: ["-jar", "DynamoDBLocal.jar", "-sharedDb", "-inMemory"]
dynamodb-localもよくよく見てみると、デフォルトでsharedDbのオプションがtrueになっていました。
const config = this.service.custom && this.service.custom.dynamodb || {};
const options = _.merge({
sharedDb: this.options.sharedDb || true,
install_path: this.options.localPath
},
config && config.start,
this.options
);
sharedDbのオプションが必要な理由は公式ドキュメントなどに記載があったので参考にしてみてください。
Discussion