2

I'm currently testing out AWS SAM with DynamoDB Local using Docker.

Here is the steps that I followed (mostly found in the internet)

  1. Create new docker network using docker network create local-dev.
  2. Run DynamoDB Local docker run -d -v "$PWD":/dynamodb_local_db -p 8000:8000 --network local-dev --name dynamodb amazon/dynamodb-local. Until this point, I'm being able to create and list tables using AWS CLI.
  3. Then, I proceed with running AWS SAM sam local start-api --docker-network local-dev. Everything looks okay.
  4. Invoked lambda.js, but it looks like no result for console.log(err)or console.log(data).

I'm not sure where could it be wrong. Please help me. Thank you in advance!

lambda.js

const services = require('./services.js');
const AWS = require('aws-sdk');

let options = {
    apiVersion: '2012-08-10',
    region: 'ap-southeast-1',
}

if(process.env.AWS_SAM_LOCAL) {
  options.endpoint = new AWS.Endpoint('http://localhost:8000')
}

const dynamoDB = new AWS.DynamoDB(options);

exports.getUser = async (event, context) => {

    let params = {};

    dynamoDB.listTables(params, (err, data) => {
        if(err) console.log(err)
            else console.log(data)
    })

    return true;
}

template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Serverless Resources


Parameters:

  FunctionsCodeBucket:
    Type: String
    Description: CodeBucket
  FunctionsCodeKey:
    Type: String
    Description: CodeKey
  FunctionsCodeVersion:
    Type: String
    Description: CodeVersion
  NodeEnv:
    Type: String
    Description: NodeEnv

Globals:
  Api:
    Cors:
      AllowMethods: "'OPTIONS,POST,GET,DELETE,PUT'"
      AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Api-Key,api-key'"
      AllowOrigin: "'*'"
  Function:
    Timeout: 300
    Runtime: nodejs10.x
    MemorySize: 128
    CodeUri: ./ 

Resources:
  DevResources:
    Type: AWS::Serverless::Function 
    Properties:                      
      Handler: "index.routes"
      Environment:
        Variables:
          NODE_ENV: !Ref NodeEnv
          # REGION: !Ref "AWS::Region"

      Policies:
      - Version: '2012-10-17'
        Statement:
        - Action:
          - dynamodb:*
          Effect: Allow
          Resource: "*"
      Events:
        GetUser:
          Type: Api 
          Properties:
            Path: /user
            Method: get
Borislav Stoilov
  • 3,247
  • 2
  • 21
  • 46
eFeN
  • 65
  • 1
  • 4

1 Answers1

3

You lambda function does not wait for dynamoDB.listTables operation. You can fix this issue by using promisified version of dynamoDB.listTables as follows:

exports.getUser = async (event, context) => {

  let params = {};

  try {
    const resp = await dynamoDB.listTables(params).promise();
    console.log(resp);
  } catch (err) {
    console.log(err)
  }
};

Another thing that you will likely need to do is to assign a network alias to your dynamodb container (you can do that using --network-alias=<container_name> option) for example, let's set the alias to dynamodb

docker run -d -v "$PWD":/dynamodb_local_db -p 8000:8000 --network local-dev --network-alias=dynamodb --name dynamodb amazon/dynamodb-local

After that you can use this network alias in your lambda function:

if(process.env.AWS_SAM_LOCAL) {
  options.endpoint = new AWS.Endpoint('http://dynamodb:8000')
}
antonku
  • 7,377
  • 2
  • 15
  • 21
  • Thanks for your help @antonku. I've tried and it works! – eFeN Nov 15 '19 at 00:01
  • @eFeN You are welcome! I would appreciate if you accept the answer if it resolves the issue, thanks! – antonku Nov 15 '19 at 09:30
  • hey i'm getting docker: Error response from daemon: network local-dev not found. – user3437721 Feb 25 '20 at 17:14
  • @user3437721 you will need `docker network create local-dev` first. For Googlers, mind that only user-defined network can use alias, the default bridge won't work, i.e. without `--network blah` command will succeed but alias will not work. – dz902 Mar 13 '20 at 15:17