ロゴテキスト ロゴ

    Serverless Frameworkの開発でDynamoDB Localを使う

    Serverless Frameworkの開発でDynamoDB Localを使う

    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を使うためのパッケージを追加

    手順が少しややこしいです。

    1. Serverless FrameworkでDynamoDB Localを使うパッケージを追加
    2. そのパッケージを使い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)コマンドが使えるようになります。

    serverless.yml
    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に追加しておきましょう。

    .gitignore
    .dynamodb

    DynamoDB Localを起動してみる

    DynamoDB Localを起動するためserverless.ymlに最低限の記述を追加します

    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 DynamoDB Localより引用



    公式にはそれ以外のオプションについても記載されていて参考になります。
    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 にアクセスすると、

    DynamoDB Localが起動した

    起動出来ている事が確認出来ました!


    stagesについて

    私の環境だとserverless.ymlにcustom.dynamodb.stagesという項目を作っています。

    serverless.yml
    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テーブルを定義します

    serverless.yml
    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.startmigrate: trueを追記します

    serverless.yml
    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);
    });

    ▶の再生マークをクリックします

    DynamoDB Localを起動し、テーブルがある事を確認出来る

    データはないけど、エラーが表示されずテーブルが存在している事が確認出来ます!


    seedデータを追加する

    これだとinMemory: trueとしているため、DynamoDB Localが起動中にデータを追加しても$ npx sls dynamodb startをする度にDynamoDB Localのデータが消えてしまいます。


    そのため、seedデータを用いてDynamoDB Local起動時に毎回データがある状態を作ります。



    まずseed用のデータを用意します、jsonファイルはどこに作っても大丈夫です。

    projectRoot/
      migrations/
        users.json
    migrations/users.json
    [
      {
        "id": 1,
        "email": "hoge@example.com"
      },
      {
        "id": 2,
        "email": "fuga@example.com"
      }
    ]


    serverless.ymlを編集し、$ npx sls dynamodb startの時にseedデータを投入するようにします。

    serverless.yml
    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データが入っている事を確認する

    Seedデータが無事入りました!

    DynamoDB Localの確認・操作を簡単にするdynamodb-adminについて

    DynamoDB Localはここまでのようにhttp://localhost:8000/shellで操作をする事が出来ます。

    しかし、お世辞にもsequelのようなGUIベースで簡単にデータを扱えるとは言い難いです。



    そこで dynamodb-adminというパッケージを使う事で確認・操作を簡単に行えるようになります!



    導入も大変ではないのでぜひ入れてみて下さい!


    dynamodb-adminの記事を別途書いたのでご参考までに〜。

    serverless.ymlに追記した部分全文

    自分の備忘録も兼ねて、
    今回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
    プロフィールの背景画像 プロフィール画像
    Yuki Takara
    都内でフリーランスのエンジニアをやってます。フロントとアプリ開発メインに幅広くやってます。