Pocket

状況

ホスト側のターミナルから見た、DynamoDb LocalのURLは、http://localhost:5003です。

ホスト側のターミナルで、aws dynamodbコマンドを使って、create-table、put-item、get-itemしました。問題ありません。

別のDockerコンテナでwebサーバを走らせています。そのwebサーバから見た、DynamoDb LocalのURLは、http://dynamodb.container:8000です。

そのWebサーバから、DynamoDB LocalへgetItemしたところ、テーブルがないよ、とエラーになってしまいました。

Error executing "GetItem" on "http://dynamodb.container:8000"; AWS HTTP error: Client error: POST http://dynamodb.container:8000 resulted in a 400 Bad Request response: {"__type":"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException","message":"Cannot do operations on a non-existent (truncated…) ResourceNotFoundException (client): Cannot do operations on a non-existent table - {"__type":"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException","message":"Cannot do operations on a non-existent table"} 

解決方法

ホスト側のターミナルで作業するときのAWS_ACCESS_KEY_IDとリージョン、Dockerコンテナのwebサーバに渡すAWS_ACCESS_KEY_IDとリージョンを同じにします。

ホスト側のターミナル

Dynamo DB LocalのAWS_ACCESS_KEY_IDとリージョンは任意です。仮に、次のようにします。

AWS_ACCESS_KEY_ID=hoge
リージョン=local

任意なので、リージョン=ap-northeast-1 にしても問題ありません。

ホスト側のターミナルでaws dynamodbコマンドを打つ前に、AWS_ACCESS_KEY_IDを設定します。

$ export AWS_ACCESS_KEY_ID=hoge
$ export AWS_SECRET_ACCESS_KEY=hogehoge

Dynamo DB Localへaws dynamodbコマンドを打つとき、--region オプションでリージョンを指定します。

$ aws dynamodb \
    --region local \
    --endpoint-url http://localhost:5003 \
    --table-name myapp_mytable \
    〜省略〜

Dockerコンテナのwebサーバ側

Dockerコンテナに渡すための環境変数の設定ファイルを作ります。ファイル名は、web.envとします。

AWS_ACCESS_KEY_ID=hoge
AWS_SECRET_ACCESS_KEY=secret

docker-compose.ymlでenv_fileを記述します。

  web:
    env_file:
      - ./web.env

PHPの場合、Aws\Sdkコンストラクタで、'region'を'local'にします。

$sdk = new Aws\Sdk([
    'endpoint' => 'http://dynamodb.container:8000',
    'region'   => 'local',
    'version'  => 'latest'
]);

DynamoDB Localのデータファイル

docker-compose.ymlで、Dockerコンテナを停止してもデータが消えないように、dbPathを設定し、Dockerコンテナの/home/dynamodblocal/dataをホスト側のディレクトリに外部マウントしました。

  dynamodb:
    tty: true
    container_name: dynamodb.container
    image: amazon/dynamodb-local
    ports:
      - 5003:8000
    command: -jar DynamoDBLocal.jar -dbPath ./data
    volumes:
      - ./dynamodb/data:/home/dynamodblocal/data

すると、ローカルの ./dynamo/data/ 下に、DynamoDB Localのデータファイルが見えるようになります。

いろいろ試したので、いくつかのファイルができています。

$ ls -1 ./dynamodb/data
AK******************_ap-northeast-1.db
AK******************_local.db
hoge_ap-northeast-1.db
hoge_local.db

つまり、[AWSアカウントID]_[リージョン].db で、分かれて保存されるんですね。

ターミナルから、AWS_ACCESS_KEY_ID=AK****、リージョン=ap-northeast-1で、テーブル作成すると、AK****_ap-northeast-1.db が作られます。

Dockerコンテナのwebサーバから、AWS_ACCESS_KEY_ID=hoge、リージョン=localで、getItemすると、hoge_local.db を読もうとします。

そのため、テーブルがないよ、とエラーになったんですね。