notebook

都内でWEB系エンジニアやってます。

dynamoDB-localでローカル開発環境を整える

【AWS発表】 デスクトップ開発を可能にする DynamoDB Local

dynamodbをローカルで扱えるようにするものだそうです

早速やってみます

インストール

  • awscliもインストールします
pip install awscli
  • 公式からダウンロードします

DynamoDB Local

curl -LO http://dynamodb-local.s3-website-us-west-2.amazonaws.com/dynamodb_local_latest
tar zxvf dynamodb_local_latest

起動

java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -port 8001 -dbPath ./db

デフォルトポートは8000番

今回ローカルでは既に8000で動かしてるものがあったので8001に

  • 動作を確認
$ aws dynamodb list-tables --endpoint-url http://192.168.30.11:8001 --profile localtest
{
    "TableNames": []
}

接続できることを確認しました

テーブルの作成

マニュアルを見ながらテーブルを追加する

AWS::DynamoDB::Table

DynamoDB 属性定義

$ aws dynamodb create-table --endpoint-url http://192.168.30.11:8002 --profile localtest --table-name tw2slack \
 --attribute-definitions AttributeName=key,AttributeType=S \
 --key-schema AttributeName=key,KeyType=HASH \
 --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
{
    "TableDescription": {
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/tw2slack",
        "AttributeDefinitions": [
            {
                "AttributeName": "key",
                "AttributeType": "S"
            }
        ],
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "WriteCapacityUnits": 1,
            "LastIncreaseDateTime": 0.0,
            "ReadCapacityUnits": 1,
            "LastDecreaseDateTime": 0.0
        },
        "TableSizeBytes": 0,
        "TableName": "tw2slack",
        "TableStatus": "ACTIVE",
        "KeySchema": [
            {
                "KeyType": "HASH",
                "AttributeName": "key"
            }
        ],
        "ItemCount": 0,
        "CreationDateTime": 1464045769.622
    }
}

テーブルが出来ました、確認してみます

$ aws dynamodb describe-table --table-name tw2slack --endpoint-url http://192.168.30.11:8001 --profile localtest
{
    "Table": {
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/tw2slack",
        "AttributeDefinitions": [
            {
                "AttributeName": "key",
                "AttributeType": "S"
            }
        ],
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "WriteCapacityUnits": 1,
            "LastIncreaseDateTime": 0.0,
            "ReadCapacityUnits": 1,
            "LastDecreaseDateTime": 0.0
        },
        "TableSizeBytes": 0,
        "TableName": "tw2slack",
        "TableStatus": "ACTIVE",
        "KeySchema": [
            {
                "KeyType": "HASH",
                "AttributeName": "key"
            }
        ],
        "ItemCount": 0,
        "CreationDateTime": 1464045769.622
    }
}

参考:

blog.cloudpack.jp

dev.classmethod.jp

操作

実際に操作してみる

dynamodb-document-js-sdk

上記を使ってtwitterから取得したツイートをslackに流すアプリのID管理部分を書いてみます

  • どこまでのツイートを流したか判断するために、最後のツイートのIDを格納する
  • 初回起動だけ0で2回目以降は値を上書き

サンプルコード

var AWS = require('aws-sdk');
AWS.config.update({endpoint: 'http://192.168.30.11:8001', region: 'localhost'});
var doc = require('dynamodb-doc');
var dynamo = new doc.DynamoDB();

var pfunc = function(err, data) {
    if (err) {
        console.log(err, err.stack);
    }
    else {
        console.log(data);
    }
}

var e = {};
e.payload = {
  "TableName": "tw2slack",
  "Key": {
    "key": "last_post_id"
  },
}

// 検索
dynamo.getItem(e.payload,function(err, data){
  if(err) {
    console.log(err);
  }
  else{
    console.dir(data);

    if ( data.Item.key ) {
      console.log('exist data');
      putItem(data.Item.value);
    }
    else {
      //新規作成
      putItem(0);
    }
  }
});

// 更新
function putItem(last_post_id){
  var params = {
    TableName: "tw2slack",
    Item: {
      key: "last_post_id",
      value: last_post_id
    }
  };

  dynamo.putItem(params,pfunc);
}

// カウンター
function incrementItem() {
  var params = {
    TableName: "tw2slack",
    Key: {
      "key": "last_post_id",
    },
    UpdateExpression: "SET #v = #v + :n",
    ExpressionAttributeNames: {"#v": "value"},
    ExpressionAttributeValues: { ":n": 1 }
  };
  dynamo.updateItem(params,pfunc);
}

動作確認用のサンプルなので実際のIDを決めうちで入れて試したりしました

最初IDを決めうちでupdateItemが使えるかと思ったのですが、updateItemでは元の値に対して何かアクションを起こすというのが前提になっているようで元の値を参照するように書かないと動かせなかったのでputItemだけで実装しました

AWS_PROFILE=localtest node dynamosample.js
{ Item: { value: 0, key: 'last_post_id' } }

罠でもなんでもないのですが、AWSの公式に書いてあるように

dynamodb-localはcredenntialファイルのaccessKeyIdとregionをもとにDBファイルを作っているようです

したがってスクリプトを実行する際にもプロファイルをあわせないといけないようです

  • ~/.aws/config
....
....
[profile localtest]
aws_access_key_id=localtest
aws_secret_access_key=localtest
region = localhost
output = json
$ ls db
localtest_localhost.db

credenntialについては下記を参考にしました

参考:

dev.classmethod.jp

組み合わせを合わせないとテーブルがあるつもりでスクリプトたたいたらテーブルないよって言われたりします

結構はまりました...

DynamoDB JavaScript console

APIドキュメントへのリンクやスニペットなど豊富にあるのでjavascript SDKで開発開発するならとても便利に使えそうです

これ知ってから開発してたらもっと時間短縮できたのに、、、

Ctrl+SPACEで補完もしてくれる!

REPLみたいな感覚で使えそうですね

アクセスはリッスンしているポートの/shell/というパスに対してアクセスするだけ

dockerで使う

dockerイメージを作って作業する場合

Dockerfileで/data以下にデータを置くように設定したので-vオプションで/data/dynamoディレクトリを作ってコンテナ側からマウントしてあげます

sudo docker run -v /data/dynamo:/data -d -p 8001:8000 test/dynamodblocal

感想

  • DynamoDB JavaScript console がすごい
    • 知らないで開発するのはしんどい
  • 次回もう少し複雑なデータを扱ってみたい
  • javascript力...

最後にDockerfileをあげておしまい

dockerfiles/dynamodb-local/