Serverless FrameworkでDynamoDBを用いる方法をご紹介します。
この記事では、最終的にServerless FrameworkでDynamoDB Localにmigrationを実行出来るようにします。
検証した環境
1 | serverless | 2.9.0 |
2 | serverless-dynamodb-local | 0.2.39 |
ローカル環境でDynamoDBを動かす環境を整える
DynamoDBをローカル環境で動かすための「DynamoDB Local」をAWSが用意してくれています
DynamoDB ローカル (ダウンロード可能バージョン) のセットアップ - Amazon DynamoDB
Serverless FrameworkのDynamoDB Localを使うためのパッケージを追加
手順が少しややこしいです。
- Serverless FrameworkでDynamoDB Localを使うパッケージを追加
- そのパッケージを使いDynamoDB Localをインストール
の順で実行します。
DynamoDB Localを先にインストールするのかな、と思ったら違うのですね。
そのためまず、Serverless FrameworkでDynamoDB Localを使うパッケージを追加
$ yarn add -D serverless-dynamodb-local
Serverless Framework(sls)でdynamodbを使えるようにする
Serverless Framework上でDynamoDB Localの操作が出来るようにserverless.ymlのplugins
に追記します。
この記述を行うことで、$npx sls dynamodb xxx
(or $yarn run sls dynamodb xxx
)コマンドが使えるようになります。
plugins:
- serverless-dynamodb-local #追加
DynamoDB Localをインストール
DynamoDB Localをインストールします。
$ npx sls dynamodb install
DynamoDBをインストールするためには$npx sls
(プロジェクト内のServerless Frameworkのコマンド)を使います。
このコマンドを実行するとプロジェクトルート配下に.dynamodb
フォルダが作られ、DynamoDB Localを実行するために必要な様々なファイルが追加されます。
projectRoot/
.dynamodb/
DynamoDBLocal_lib/
third_party_licenses/
DynamoDBLocal.jar
・・・
package.json
serverless.yml
プロジェクトメンバーには$npx dynamodb install
を実行してもらえば良いので、.dynamodb/
は.gitignoreに追加しておきましょう。
.dynamodb
DynamoDB Localを起動してみる
DynamoDB Localを起動するためserverless.ymlに最低限の記述を追加します
custom:
dynamodb:
stages: #stagesについては後述
- dev
start:
inMemory: true
inMemory: true
はメモリ上で実行する事でデータを永続化しません。
公式には↓のように書かれています
DynamoDB; will run in memory, instead of using a database file. When you stop DynamoDB;, none of the data will be saved. Note that you cannot specify both -dbPath and -inMemory at once.
データベースファイルを使用する代わりに、メモリ内で実行されます。 DynamoDB;を停止すると、データは保存されません。 -dbPathと-inMemoryの両方を同時に指定することはできないことに注意してください。(google翻訳)
公式にはそれ以外のオプションについても記載されていて参考になります。
(serverless.ymlの記述内容ではなくCLIのコマンドのオプションについてのため違う部分もあるかもしれません)
--port -p Port to listen on. Default: 8000
--cors -c Enable CORS support (cross-origin resource sharing) for JavaScript. You must provide a comma-separated "allow" list of specific domains. The default setting for -cors is an asterisk (*), which allows public access.
--inMemory -i DynamoDB; will run in memory, instead of using a database file. When you stop DynamoDB;, none of the data will be saved. Note that you cannot specify both -dbPath and -inMemory at once.
--dbPath -d The directory where DynamoDB will write its database file. If you do not specify this option, the file will be written to the current directory. Note that you cannot specify both -dbPath and -inMemory at once. For the path, current working directory is <projectroot>/node_modules/serverless-dynamodb-local/dynamob. For example to create <projectroot>/node_modules/serverless-dynamodb-local/dynamob/<mypath> you should specify -d <mypath>/ or --dbPath <mypath>/ with a forwardslash at the end.
--sharedDb -h DynamoDB will use a single database file, instead of using separate files for each credential and region. If you specify -sharedDb, all DynamoDB clients will interact with the same set of tables regardless of their region and credential configuration.
--delayTransientStatuses -t Causes DynamoDB to introduce delays for certain operations. DynamoDB can perform some tasks almost instantaneously, such as create/update/delete operations on tables and indexes; however, the actual DynamoDB service requires more time for these tasks. Setting this parameter helps DynamoDB simulate the behavior of the Amazon DynamoDB web service more closely. (Currently, this parameter introduces delays only for global secondary indexes that are in either CREATING or DELETING status.)
--optimizeDbBeforeStartup -o Optimizes the underlying database tables before starting up DynamoDB on your computer. You must also specify -dbPath when you use this parameter.
--migration -m After starting dynamodb local, run dynamodb migrations.
DynamoDB Localを起動してみます。
$ npx sls dynamodb start
Dynamodb Local Started, Visit: http://localhost:8000/shell
2021-01-11 16:21:21.519:INFO::main: Logging initialized @1156ms to org.eclipse.jetty.util.log.StdErrLog
http://localhost:8000/shell にアクセスすると、
起動出来ている事が確認出来ました!
stagesについて
私の環境だとserverless.ymlにcustom.dynamodb.stages
という項目を作っています。
custom:
dynamodb:
stages:
- dev
もしこの記述を行わなかった場合、
$ npx sls dynamodb start
Serverless: Skipping start: DynamoDB Local is not available for stage: dev
と表示されてDynamoDB Localが起動出来ないため、記載しています。
そのため、stages
の部分を削除しても動く人は削除して問題ないと思います。
以下のissueを参考しました。
DynamoDB Local is not available for stage when loading from file · Issue #229 · 99x/serverless-dynamodb-local
migrationを実行する
テーブルの定義はserverless.ymlのresources
に記載します。
Serverless Frameworkのresourcesの公式ページを参考にusers
テーブルを定義します
resources: # CloudFormation template syntax
Resources:
usersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: users
AttributeDefinitions:
- AttributeName: email
AttributeType: S
KeySchema:
- AttributeName: email
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
email(文字列)をプライマリーキーのように扱うシンプルなテーブルですね。
先ほどのcustom.dynamodb.start
にmigrate: true
を追記します
custom:
dynamodb:
stages:
- dev
start:
inMemory: true
migrate: true
これで改めてsls dynamodb start
を実行してみると
$ npx sls dynamodb start
Dynamodb Local Started, Visit: http://localhost:8000/shell
2021-01-11 16:59:46.987:INFO::main: Logging initialized @1019ms to org.eclipse.jetty.util.log.StdErrLog
Serverless: DynamoDB - created table users
Serverless: DynamoDB - created table users
usersテーブルが作成出来た模様。
http://localhost:8000/shell にアクセスして左の欄に以下のコードを入力し、
var params = {
TableName: 'users',
};
dynamodb.scan(params, function(err, data) {
if (err) ppJson(err);
else ppJson(data);
});
▶の再生マークをクリックします
データはないけど、エラーが表示されずテーブルが存在している事が確認出来ます!
seedデータを追加する
これだとinMemory: true
としているため、DynamoDB Localが起動中にデータを追加しても$ npx sls dynamodb start
をする度にDynamoDB Localのデータが消えてしまいます。
そのため、seedデータを用いてDynamoDB Local起動時に毎回データがある状態を作ります。
まずseed用のデータを用意します、jsonファイルはどこに作っても大丈夫です。
projectRoot/
migrations/
users.json
[
{
"id": 1,
"email": "hoge@example.com"
},
{
"id": 2,
"email": "fuga@example.com"
}
]
serverless.ymlを編集し、$ npx sls dynamodb start
の時にseedデータを投入するようにします。
custom:
dynamodb:
stages:
- dev
start:
inMemory: true
migrate: true
seed: true
seed:
development:
sources:
- table: users
sources: [ ./migrations/users.json ]
これで$ npx sls dynamodb start
を実行すると
$ npx sls dynamodb start
Dynamodb Local Started, Visit: http://localhost:8000/shell
2021-01-11 19:53:38.178:INFO::main: Logging initialized @868ms to org.eclipse.jetty.util.log.StdErrLog
Serverless: DynamoDB - created table users
Seed running complete for table: users
Seed running complete for table: users
最後にSeedデータが投入されてそうです!
http://localhost:8000/shell にアクセスし、先ほどと同じコードを入力すると、
Seedデータが無事入りました!
DynamoDB Localの確認・操作を簡単にするdynamodb-adminについて
DynamoDB Localはここまでのようにhttp://localhost:8000/shell
で操作をする事が出来ます。
しかし、お世辞にもsequelのようなGUIベースで簡単にデータを扱えるとは言い難いです。
そこで dynamodb-admin
というパッケージを使う事で確認・操作を簡単に行えるようになります!
導入も大変ではないのでぜひ入れてみて下さい!
dynamodb-admin
の記事を別途書いたのでご参考までに〜。
serverless.ymlに追記した部分全文
自分の備忘録も兼ねて、
今回serverless.ymlに追記した部分と簡単なコメントを合わせて載せておきます
# slsコマンドで `sls dynamodb install` などを実行する上でも必要
plugins:
- serverless-dynamodb-local
custom:
dynamodb:
# dymanodb start時に起動が出来ないため記載、起動が出来るのであれば書かなくて問題ない
stages:
- dev
# dymanodb start実行時の設定
# 以下の場合
# - データの永続化はしない(inMemory: true)
# - migration実行とseedデータの投入をstart時に実行
start:
inMemory: true
migrate: true
seed: true
seed:
development:
sources:
- table: programs
sources: [ ./migrations/users.json ]
# usersテーブルの定義
# migrationを実行した際にこの定義を元にテーブルを作る
resources:
Resources:
usersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: users
AttributeDefinitions:
- AttributeName: email
AttributeType: S
KeySchema:
- AttributeName: email
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1