来自Node-aws的Dynamo本地:所有操作都失败,“无法对不存在的表执行操作”。

57

我有一个本地运行的DynamoDB。我已经使用JavaScript控制台设置了我的表格,它们从那里列出得很好。

我还可以在JavaScript控制台中放置和获取我的表格中的项目:

var params = { TableName:"environmentId", Item: { environmentId: {"S":"a4fe1736-98cf-4560-bcf4-cc927730dd1b"} }};
dynamodb.putItem(params, function(err, data) {
    console.log("put : err was " + JSON.stringify(err) + " and data is " + JSON.stringify(data));
});

输出 put : err was null and data is {} ,我认为这是“成功”,因为

params = { "Key":{"environmentId":{"S":"a4fe1736-98cf-45e0-bcf4-cc927730dd1b"}},"TableName":"environmentId"}
dynamodb.getItem(params, function(err, data) {
    console.log("get : err was " + JSON.stringify(err) + " and data is " + JSON.stringify(data));
});

打印出get: err was null and data is {"Item":{"environmentId":{"S":"a4fe1736-98cf-45e0-bcf4-cc927730dd1b"}}},即它检索刚刚放入表格的对象。

但是,如果启动节点REPL并键入:

var AWS = require('aws-sdk');
AWS.config.loadFromPath("./config/credentials.js");
endpoint = new AWS.Endpoint("http://localhost:8000");
var dynamoOpts = {apiVersion: '2012-08-10', 'endpoint':endpoint};
var dynamodb = new AWS.DynamoDB(dynamoOpts);
var params = { TableName:"environmentId", Item: { environmentId: {"S":"a4fe1736-98cf-4560-bcf4-cc927730dd1b"} }};
dynamodb.putItem(params, function(err, data) {
    console.log("put : err was " + JSON.stringify(err) + " and data is " + JSON.stringify(data));
}
我遇到了一个资源未找到的错误:
{ "message":"Cannot do operations on a non-existent table",
    "code":"ResourceNotFoundException",
    "time":"2015-04 10T10:01:26.319Z",
    "statusCode":400,
    "retryable":false,
    "retryDelay":0
}

从putCommand返回的ASW.request对象具有正确的端点:

{ protocol: 'http:',
    host: 'localhost:8000',
    port: 8000,
    hostname: 'localhost',
    pathname: '/',
    // etc.

我的Node应用程序发生了同样的事情,但是连接到真实的AWS托管DynamoDB的相同代码却可以正常工作。


2
同样适用于其他语言,.NET也是如此。 - Brett Bim
3个回答

80
问题在于JavaScript控制台和你的应用程序使用不同的配置文件(凭证和区域),因此DynamoDB Local将为它们创建单独的数据库文件。通过在启动本地DynamoDB时使用-sharedDb标志,所有客户端将共享单个数据库文件。
来自文档
-sharedDb - DynamoDB Local将使用单个数据库文件,而不是为每个凭据和区域使用单独的文件。如果指定-sharedDb,则所有DynamoDB Local客户端将与相同的表集交互,无论其区域和凭证配置如何。

1
谢谢。从那个文档行中,JavaScript控制台将使用不同的数据库这一事实对我来说并不清楚。 - Rog
1
您可以使用设置了卷的Docker容器 - docker run -d -p 8000:8000 -v /tmp/data:/data/ dwmkerr/dynamodb -dbPath /data/使用Docker在本地运行Amazon DynamoDB注意:您需要在Dynamo JS shell上设置Access Key Id以避免DynamoDB Local失去表格 - Richard Lee
1
现在在Docker Hub上有一个来自亚马逊的官方Docker镜像。https://hub.docker.com/r/amazon/dynamodb-local/ - wassgren
非常感谢!我希望早点看到这个。 - gigi2
我个人对所有事情都有控制权,所以最好让我保留内存表,并确保所有测试夹具中的区域和凭据都是相同的。尽管如此,在找到最后一组错误凭据之前,我确实不得不在8000端口上运行tcpdump。 - vastlysuperiorman

50

使用官方DynamoDB本地 Docker镜像的用户应该使用以下命令行启动,以启用sharedDb

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

可以在docker inspect amazon/dynamodb-local的输出中看到镜像使用的原始ENTRYPOINTCMD

"Entrypoint": [
    "java"
]
"Cmd": [
    "-jar",
    "DynamoDBLocal.jar",
    "-inMemory"
]

所以我们基本上需要复制它们并添加 -sharedDb


9
亲爱的上帝,你是救星! - Jason
7
嗯,我该说什么呢?我欠你大约40个小时的生命。 - dz902
我遇到了这个错误:“无法识别的选项:-inMemory” - S A
或者,确保所有客户端使用相同的访问密钥 ID 和正确的区域。 - Shannon

2
如果您正在使用CircleCI,这是您的执行程序应该如何看起来:

# using service containers on CircleCI
# https://circleci.com/docs/2.0/databases/
executors:
  with-dynamodb:
    docker:
      # image used to install source code,
      # run our server and run Cypress tests
      - image: cypress/base:14.17.3

      # image used to run Dynamodb in a separate container
      - image: amazon/dynamodb-local:1.17.0
        # HERE IS THE IMPORTANT PART
        command: ["-jar", "DynamoDBLocal.jar", "-inMemory", "-sharedDb"]

command 选项允许您覆盖 Dockerfile 中默认的 CMD,如 @madhead 所指出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接