AWS DynamoDB Local 触ったらハマった

aws コマンドで作成したテーブルが Web の Javascript Shell から見れなかったのでいろいろ調べた。

確認

試してた GitHub リポジトリがこちら
https://github.com/hondash/demo-aws-sam-local

aws コマンド経由

config を設定

$ aws configure

AWS Access Key ID [None]: xxxxxxxxxxxxxxxxxx
AWS Secret Access Key [None]: xxxxxxxxxxxxxxxxxx
Default region name [None]: ap-northeast-1
Default output format [None]: json

テーブルを作る

$ aws dynamodb create-table \
    --table-name test_via_aws_command \
    --attribute-definitions AttributeName=name,AttributeType=S AttributeName=age,AttributeType=N \
    --key-schema AttributeName=name,KeyType=HASH AttributeName=age,KeyType=RANGE \
    --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 \
    --endpoint=http://localhost:8000

テーブル一覧を取得

$ aws dynamodb list-tables --endpoint=http://localhost:8000

{
    "TableNames": [
        "test_via_aws_command"
    ]
}

ブラウザ経由

http://localhost:8000/shell/ からテーブルを作る

var params = {
    TableName: 'test_via_web',
    KeySchema: [ 
        { 
            AttributeName: 'id',
            KeyType: 'HASH',
        },
    ],
    AttributeDefinitions: [
        {
            AttributeName: 'id',
            AttributeType: 'N',
        },
    ],
    ProvisionedThroughput: {
        ReadCapacityUnits: 1, 
        WriteCapacityUnits: 1, 
    },
};
dynamodb.createTable(params, function(err, data) {
    if (err) ppJson(err);
    else ppJson(data);
});

テーブル一覧を取得

var params = {};
dynamodb.listTables(params, function(err, data) {
    if (err) ppJson(err);
    else ppJson(data);
});

aws コマンドでテーブル一覧を再度取得

$ aws dynamodb list-tables --endpoint=http://localhost:8000

{
    "TableNames": [
        "test_via_aws_command"
    ]
}

結果

  • ブラウザ
    • aws コマンド経由で作成したテーブルがない
  • aws コマンド
    • Web 経由で作成したテーブルがない

何が起きたか?

-sharedDb を指定した場合、DynamoDB では、認証情報やリージョンごとに別のファイルを使用せずに、単一のデータベースファイルを使用します。
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DynamoDBLocal.html

「DynamoDB では、認証情報やリージョンごとに別のファイルを使用」

つまりブラウザシェルが認証情報とリージョンを見ておらず、別のデータベースファイルを作っていた。
[access key ID]_[region name].db というファイルが作成されている (フォーマットは SQLite)

解決方法

  1. 起動オプションに -sharedDb をつける。
    (shared-local-instance.db というファイルに全部詰め込まれる)
  2. 生成される [access key ID]_[region name].db をコマンドと Web で同じものを見るようにすれば良い。
    1. 赤丸の部分をクリックすると access key ID を入力できるので [access key ID] を一致させる。
    2. Webのターミナルで以下のコードを実行しておくとリージョンを指定できるので [region name] を一致させる。
      dynamodb.config.update({
       region: "ap-northeast-1"
      })
      

余談

ちなみに SAM Local でもリージョン見てくれない問題がある

https://github.com/awslabs/aws-sam-cli/issues/175

aws configure で指定したリージョンを sam コマンドでは拾ってくれず、 us-east-1 になる。

sam local での解決方法は、

  1. aws configure のリージョンを us-east-1 にしてしまう
  2. AWS_REGION=ap-northeast-1 sam ... という形式で実行する