How to connect to local DynamoDb on Docker from local aws sam lambda node js function

An alternative to performing development in the online aws sam console editor site, is to develop on your local machine and test it there also.

Create a shared docker network for your two docker images to run on (dynamodb and sam lambda)

 docker network create lambda-local

Specify a name of the docker container. Nodejs will use that name to connect to the dynamodb (instead of 127.0.0.1 or localhost). Even though we as outsiders see them running on 127.0.0.1 — they on the other hand see themselves in a different context, so the dynamodb name lets the db be seen by the lambda function using that name.

The -sharedDb means different aws sam lambdas are accessing the same local database. Those functions should not specify the aws region in their aws config code before connecting to the database. When dynamodb is used locally – it doesn’t support different regions.

docker run -p 8000:8000 --network lambda-local --name dynamodb dwmkerr/dynamodb -sharedDb

A test – specifying the shared docker network we created:

sam local invoke YourFunctionName --event event.json --docker-network lambda-local

An example node js lambda function:

const AWS = require('aws-sdk');

var dynamoDb = 
  new AWS.DynamoDB.DocumentClient({    
    endpoint: 'http://dynamodb:8000'
  });

exports.handler = function(event, context) {

    console.log('Starting handler!...');

    var params = {
        TableName: 'YOUR_TABLE_NAME',
      };
     
      dynamoDb.scan(params, (error, result) => {

        if (error) {
          console.log('Error! ' + error);          
        }else{
            console.log('Success!' + result);
        }    
      });
};

Sample section of a sam yaml template: function and dynamo db resources

Resources:

    YourFunctionName: 
        Type: AWS::Serverless::Function 
        Properties:
            CodeUri: get-something/
            Handler: app.handler
            Runtime: nodejs8.10
            Events:
                GetStories:
                    Type: Api 
                    Properties:
                        Path: /get-something
                        Method: get

    DynamoDBTable:
        Type: AWS::DynamoDB::Table
        Properties:
            TableName: YOUR_TABLE_NAME
            ProvisionedThroughput:
                WriteCapacityUnits: 1
                ReadCapacityUnits: 1
            AttributeDefinitions:
                - AttributeName: id
                  AttributeType: S
            KeySchema:
                - KeyType: HASH
                  AttributeName: id

Note! Just specifying the table as a resource in the sam yaml template is not enough. It does not create the table for you in the db. One good option for creating the table is to use the dynamo db web console that will be available to you after you started the dynamo db container in docker on your specified port ex::

http://localhost:8000/shell/

In that db web console – it has convenience code inserts that give you the format of how you can create your table ex:

var params = {
    TableName: 'MY_TABLE_NAME',
    KeySchema: [ // The type of of schema.  Must start with a HASH type, with an optional second RANGE.
        { // Required HASH type attribute
            AttributeName: 'id',
            KeyType: 'HASH',
        }
    ],
    AttributeDefinitions: [ // The names and types of all primary and index key attributes only
        {
            AttributeName: 'id',
            AttributeType: 'S', // (S | N | B) for string, number, binary
        }
    ],
    ProvisionedThroughput: { // required provisioned throughput for the table
        ReadCapacityUnits: 1, 
        WriteCapacityUnits: 1, 
    }
};
dynamodb.createTable(params, function(err, data) {
    if (err) ppJson(err); // an error occurred
    else ppJson(data); // successful response

});

Notice you don’t and shouldn’t specify all the columns when creating the table. You should only be specifying the columns that are to be keys. Specifying extra non-key columns will cause the create table command to fail.

If instead of using the dynamodb web console to create the table – you use the aws command: make sure you specify the endpoint url correctly

aws dynamodb create-table --cli-input-json file://yourTableDef.json --endpoint-url http://localhost:8000

Note that assumes it’s running on port 8000 and you provided a json file that looks something like:

{
  "TableName": "YOUR_TABLE_NAME",
  "KeySchema": [
    { "AttributeName": "id", "KeyType": "HASH"}
  ],
  "AttributeDefinitions": [
    {"AttributeName": "id", "AttributeType": "S"}
  ],
  "ProvisionedThroughput": {
      "ReadCapacityUnits": 5,
      "WriteCapacityUnits": 5
  }
}

References:

https://stackoverflow.com/questions/48926260/connecting-aws-sam-local-with-dynamodb-in-docker

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.UsageNotes.html

https://blog.kongregate.com/serverless-up-and-running/

2 thoughts on “How to connect to local DynamoDb on Docker from local aws sam lambda node js function

  1. Thank you for this article, I was struggling to connect local docker dynamodb with my nodeapp running aws-sdk. Your article was just what I needed, thank you!

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s