vogels icon indicating copy to clipboard operation
vogels copied to clipboard

Dynamodb Error: Nodejs App with dynamodb does not work in docker but works without it

Open helloravi opened this issue 8 years ago • 6 comments

I made a simple nodejs app with only one table in dynamodb. I am using Vogels as the datawrapper. It works very well if I do not dockerize it.

I tried running the docker exactly the way I run the app in development mode too. That too did not work.

Here is the code I use to create tables:

module.exports = function () {
	const vogels = require('vogels');
    // const AWS= require('aws-sdk');
    const Lr = require("../api/models/LRModel");
    if (process.env.NODE_ENV === "test") {
        AWS.config.update({ accessKeyId: "myKeyId", secretAccessKey: "secretKey", region: "us-west-2" });
        vogels.dynamoDriver(new AWS.DynamoDB({ endpoint: 'http://localhost:8000' }));
    } else {
        console.log("AWS access key=", process.env.AWS_ACCESS_KEY, "AWS Secret key=", process.env.AWS_SECRET_KEY, "AWS Region =", process.env.AWS_REGION);
        vogels.AWS.config.update({accessKeyId: process.env.AWS_ACCESS_KEY, secretAccessKey: process.env.AWS_SECRET_KEY, region: process.env.AWS_REGION, sslEnabled: false });

    }

	vogels.createTables({
		'lrs': {readCapacity: 10, writeCapacity: 10}
	}, function(err) {
		if (err) {
			console.log('Error creating tables: ', err);
		} else {
			console.log('Tables have been created');
		}
	});
}

Here is the error I get in docker:

server-0   | Error creating tables:  { TimeoutError: Missing credentials in config
server-0   |     at ClientRequest.<anonymous> (/app/node_modules/vogels/node_modules/aws-sdk/lib/http/node.js:61:34)
server-0   |     at ClientRequest.g (events.js:291:16)
server-0   |     at emitNone (events.js:86:13)
server-0   |     at ClientRequest.emit (events.js:185:7)
server-0   |     at Socket.emitTimeout (_http_client.js:626:10)
server-0   |     at Socket.g (events.js:291:16)
server-0   |     at emitNone (events.js:86:13)
server-0   |     at Socket.emit (events.js:185:7)
server-0   |     at Socket._onTimeout (net.js:339:8)
server-0   |     at ontimeout (timers.js:365:14)
server-0   |   message: 'Missing credentials in config',
server-0   |   code: 'CredentialsError',
server-0   |   time: 2017-06-29T05:36:23.724Z,
server-0   |   originalError:
server-0   |    { message: 'Could not load credentials from any providers',
server-0   |      code: 'CredentialsError',
server-0   |      time: 2017-06-29T05:36:23.724Z,
server-0   |      originalError:
server-0   |       { message: 'Missing credentials in config',
server-0   |         code: 'CredentialsError',
server-0   |         time: 2017-06-29T05:36:23.721Z,
server-0   |         originalError: [Object] } } }

One thing I clearly notice when I run it WITHOUT docker is that the dynamodb end point is a httpS end point. Here is the endpoint logged from https://github.com/aws/aws-sdk-js/blob/8904e9c730fb2fccf9d201f66266a6e2cbb75348/lib/http/node.js
(line number 13).

server-0   |   Endpoint {
server-0   |   protocol: 'https:',
server-0   |   host: 'dynamodb.us-west-1.amazonaws.com',
server-0   |   port: 443,
server-0   |   hostname: 'dynamodb.us-west-1.amazonaws.com',
server-0   |   pathname: '/',
server-0   |   path: '/',
server-0   |   href: 'https://dynamodb.us-west-1.amazonaws.com/',
server-0   |   constructor: { [Function: Endpoint] __super__: [Function: Object] } }

When I run it WITH docker is that the dynamodb end point is a http end point. Here is the endpoint logged from https://github.com/aws/aws-sdk-js/blob/8904e9c730fb2fccf9d201f66266a6e2cbb75348/lib/http/node.js
(line number 13).

server-0   |   Endpoint {
server-0   |   protocol: 'http:',
server-0   |   host: '169.254.169.254',
server-0   |   port: 80,
server-0   |   hostname: '169.254.169.254',
server-0   |   pathname: '/latest/meta-data/iam/security-credentials/',
server-0   |   path: '/latest/meta-data/iam/security-credentials/',
server-0   |   href: 'http://169.254.169.254/latest/meta-data/iam/security-credentials/' }

Where am I going wrong with this?

helloravi avatar Jun 29 '17 08:06 helloravi

What is the output of:

console.log("AWS access key=", process.env.AWS_ACCESS_KEY, "AWS Secret key=", process.env.AWS_SECRET_KEY, "AWS Region =", process.env.AWS_REGION);

Are there any values for those environment variables? If their values are not setted you should configure your user (which runs your docker) to set those environment variables from somewhere.

Also try to put the credential keys directly in the code instead of getting them from the user's environment... Probably it is an environment issue.

set-killer avatar Jun 29 '17 09:06 set-killer

All the values work. I hard coded them to check. That did not work either with docker.

I have been struggling with this for a couple of days. Let me know if i have to add any other details to this. Thanks for taking the time to respond

helloravi avatar Jun 29 '17 09:06 helloravi

In that case I guess you have 2 options: process.env.NODE_ENV === "test" equals true so it tries to connect to the local aws, Or your access keys are incorrect. You may try to issue new keys.

If you run env inside the docker with the user which is going to run the application you should see your access keys... And why are putting this option: sslEnabled: false

set-killer avatar Jun 29 '17 11:06 set-killer

There is a point of analysis which I did not highlight it enough.

  1. It works very well if I dont dockerize it. Just run it with `npm run dev'.
  2. Initially I did not put sslEnabled: false. After I saw the end point log from node.js in aws-sdk I wanted to make both the calls http(without S). There is no change with or without sslEnabled.

helloravi avatar Jun 30 '17 01:06 helloravi

Well then, the problem is in your docker configuration. Perhaps you should ask their community.

As you know the docker container runs in sandboxed environment, which means it does not have access to the outside "world". You should put your AWS credentials inside the docker container and configure the user which runs the APP inside the container to have those environment credentials...

Also ssl enabled is highly recommended since you may have sensitive information transferred from dynamoDB to your server such as users password and etc...

set-killer avatar Jun 30 '17 09:06 set-killer

@helloravi If you are using EC2, recommended way is to use IAM role to allow DynamoDB access and this will work for Docker apps. Using roles you don't need to pass Access key, Vogels will detect it automatically.

avtaniket avatar Sep 08 '17 14:09 avtaniket