DynamoDB local のあれこれ

こんにちは、会計フリーのエンジニアをやっている id:mihyaeru21 です。 この記事はfreee Developers Advent Calendar 2019の8日目のものです。 昨日は id:ymizushi によるfreee社宅管理でSVGを使ってシミュレータ描画を行った話でした。 React で SVG を操作するのは色々できそうで夢が広がりますね!

今日は DynamoDB local のあれこれについて書きます。

DynamoDB local とは

DynamoDB local は AWS が公式で用意しているダウンロード可能な DynamoDB の実装です。 開発環境やテストで使用することが想定されています。 jar として配布されている他、 Docker image として Docker Hub でも配布されていて、以下のコマンドでお手軽に実行することができます。

$ docker run -p 8000:8000 amazon/dynamodb-local

データの永続化

上記の実行方法だと停止時にデータが消失してしまうため、CI環境はともかくローカルの開発環境で使うには少し不便です。 データを永続化する方法も用意されています。 公式の説明に各種オプションの説明が載っています。

この Docker image は ENTRYPOINTjava に、 CMD["-jar" "DynamoDBLocal.jar" "-inMemory"] になっているため、デフォルトではメモリ上にのみデータを保持するような設定で動いています 。 以下のように起動するとコンテナ内のファイルとして保存されるようになります。 (実際には直接 docker コマンドで起動することは少ないかもしれませんが、ここでは簡単のため docker コマンドで実行しつつ説明していきます。)

$ docker run -p 8000:8000 amazon/dynamodb-local -jar DynamoDBLocal.jar

こうやって起動したときに何が起きているのかを知るために、コンテナに潜ってみます。

[dynamodblocal@fc266bcfc875 ~]$ pwd
/home/dynamodblocal

[dynamodblocal@fc266bcfc875 ~]$ ls -1
DynamoDBLocal.jar
DynamoDBLocal_lib
LICENSE.txt
README.txt
third_party_licenses

それっぽいファイルがある状態です。 この状態で以下のコマンドでテーブルを作成してみます。

$ env AWS_ACCESS_KEY_ID=dummy AWS_SECRET_ACCESS_KEY=dummykey aws dynamodb --region ap-northeast-1 --endpoint-url http://localhost:8000 create-table --table-name hoge --key-schema AttributeName=id,KeyType=HASH --attribute-definitions AttributeName=id,AttributeType=S --billing-mode PAY_PER_REQUEST

すると dummy_ap-northeast-1.db というファイルが作成されました。

[dynamodblocal@fc266bcfc875 ~]$ ls -1
DynamoDBLocal.jar
DynamoDBLocal_lib
LICENSE.txt
README.txt
dummy_ap-northeast-1.db
third_party_licenses

AWS_ACCESS_KEY_ID ごとリージョンごとに別々に管理される仕様となっています。 例えば AWS_ACCESS_KEY_ID=dummy2 で再度同じコマンドを実行してテーブルを作成すると dummy2_ap-northeast-1.db というファイルが作成されます。 これについても公式で説明されています。

sharedDb

ローカルでそこまで分離したい用途はあまり無さそうどころか、「さっき作ったテーブルが見えないぞ???」という状態に陥いって時間を溶かしてしまうことがあります。 これを解決するオプションも用意されています。 -sharedDb を設定するとファイルが AWS_ACCESS_KEY_ID やリージョンで分離されず shared-local-instance.db というファイル名で共通になります。

$ docker run -p 8000:8000 amazon/dynamodb-local -jar DynamoDBLocal.jar -sharedDb

今までと同じコマンドでテーブルを作成するとそれっぽいものが作成されます。

[dynamodblocal@770644dc6a85 ~]$ ls -1
DynamoDBLocal.jar
DynamoDBLocal_lib
LICENSE.txt
README.txt
shared-local-instance.db
third_party_licenses

この状態で別の AWS_ACCESS_KEY_ID やリージョンが違うリクエストを投げても今作ったテーブルが見えるようになっており、共通になっていることがわかります。

$ env AWS_ACCESS_KEY_ID=dummy2 AWS_SECRET_ACCESS_KEY=dummysec aws dynamodb --region us-east-1 --endpoint-url http://localhost:8000 list-tables
{
    "TableNames": [
        "hoge"
    ]
}

データを Volume に置く

このままではコンテナが破棄されるとデータがなくなるので Volume をマウントしたいです。

$ docker run -p 8000:8000 -v dynamodb:/home/dynamodblocal amazon/dynamodb-local -jar DynamoDBLocal.jar -sharedDb

これでOKです。

起動ごとにテーブルを最適化する -optimizeDbBeforeStartup というオプションがあるので、それも設定しておきます。 これを設定するためには -dbPath も明示的に設定する必要があります。 最終形は↓になります。

まとめ

最終的にはこう実行したら良さげです。

$ docker run -p 8000:8000 -v dynamodb:/home/dynamodblocal amazon/dynamodb-local -jar DynamoDBLocal.jar -sharedDb -dbPath . -optimizeDbBeforeStartup

Docker Compose の場合はこうなります。

version: '3'
services:
  dynamodb:
    image: amazon/dynamodb-local
    command: -jar DynamoDBLocal.jar -sharedDb -dbPath . -optimizeDbBeforeStartup
    volumes:
      - dynamodb:/home/dynamodblocal
    ports:
      - 8000:8000
volumes:
  dynamodb:
    driver: local

ちなみに、 DynamoDB 以外にも動作させたいサービスがある場合は個々に起動させるのではなく LocalStack が便利かもしれません。

freee Developers Advent Calendar 2019 明日は id:teppei-studio が担当です。 よろしくおねがいします!