I've deployed a custom Node.js app on Google App engine engine successfully. However I'm having issues starting the app because mongoose times out when attempting to connect. Frustratingly, the mongoose connects just fine on my local machine with the exact same parameters.
My MongoDb URI is of the form:
mongodb://<dbuser>:<dbpassword>@xxxx.mlab.com:<portNumber>/db-name
As the URI implies, the db is hosted by mlab. It is a sandbox instance on Google Cloud Platform. I however did not deploy the db with Google Compute Engine. I merely opted to host in on GCP when going through the setup process on mlab.
I've come across similar questions on SO but most of them do not have an accepted answer. Just varying discourse in comments with no accepted solution.
My question therefore is, what differs between my App Engine instance and my local computer when trying to connect to the above URI? Does the fact that I chose for mlab to host it on GCP matter? Would it be any different if I chose for it to be hosted on Amazon AWS? What exactly is the root cause of the issue?
For reference, here are similar questions I've found:
error connecting to mongodb with mongoose on google compute engine
Cannot connect to mongodb after app deploys on google app engine
Also, if it helps, mongodb is used as the db for business models, the datastore for the app's Express Session, and for storing transient data from socket.io.
Error stacktrace from App Engine after deployment:
2017-10-18 02:13:46 default[20171017t215757] npm ERR! enoent ENOENT: no such file or directory, open '/app/package.json'
2017-10-18 02:13:46 default[20171017t215757] npm ERR! enoent ENOENT: no such file or directory, open '/app/package.json'
2017-10-18 02:13:46 default[20171017t215757] npm ERR! enoent This is most likely not a problem with npm itself
2017-10-18 02:13:46 default[20171017t215757] npm ERR! enoent and is related to npm not being able to find a file.
2017-10-18 02:13:46 default[20171017t215757] npm ERR! enoent
2017-10-18 02:13:46 default[20171017t215757]
2017-10-18 02:13:46 default[20171017t215757] npm ERR! Please include the following file with any support request:
2017-10-18 02:13:46 default[20171017t215757] npm ERR! /app/npm-debug.log
2017-10-18 02:23:41 default[20171017t215757] npm ERR! Linux 3.16.0-4-amd64
2017-10-18 02:23:41 default[20171017t215757] npm ERR! argv "/nodejs/bin/node" "/nodejs/bin/npm" "start"
2017-10-18 02:23:41 default[20171017t215757] npm ERR! node v6.11.3
2017-10-18 02:23:41 default[20171017t215757] npm ERR! npm v3.10.10
2017-10-18 02:23:41 default[20171017t215757] npm ERR! path /app/package.json
2017-10-18 02:23:41 default[20171017t215757] npm ERR! code ENOENT
2017-10-18 02:23:41 default[20171017t215757] npm ERR! errno -2
2017-10-18 02:23:41 default[20171017t215757] npm ERR! syscall open
Error stacktrace from running app locally in Google Cloud Shell:
/home/myuser/src/project-id/teammate-express-server/node_modules/mongodb/lib/mongo_client.js:421
throw err
^
MongoError: failed to connect to server [ds147454.mlab.com:47454] on first connect [MongoError: connection 1 to ds147454.mlab.com:47454 timed out]
at Pool.<anonymous> (/home/myuser/src/project-id/teammate-express-server/node_modules/mongodb-core/lib/topologies/server.js:336:35)
at emitOne (events.js:96:13)
at Pool.emit (events.js:188:7)
at Connection.<anonymous> (/home/myuser/src/project-id/teammate-express-server/node_modules/mongodb-core/lib/connection/pool.js:280:12)
at Connection.g (events.js:292:16)
at emitTwo (events.js:106:13)
at Connection.emit (events.js:191:7)
at Socket.<anonymous> (/home/myuser/src/project-id/teammate-express-server/node_modules/mongodb-core/lib/connection/connection.js:197:10)
at Socket.g (events.js:292:16)
at emitNone (events.js:86:13)
at Socket.emit (events.js:185:7)
at Socket._onTimeout (net.js:338:8)
at ontimeout (timers.js:386:14)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
As it's been pointed out, you can follow the instruction on https://cloud.google.com/nodejs/getting-started/deploy-mongodb to configure Google App Engine using
config.json
file. (update: link no longer works, try: https://cloud.google.com/community/tutorials/nodejs-mongodb-on-appengine instead)Since you're using
mongoose
the models will dictate the collection usage. i.e. save(), update(). If you're connecting usingnode.js
directly, you can also change database/collection easily in the code.Google App Engine is a fully managed platform. It is in a sense serverless, you are utilising a pool of workers to up/down scale your application. When a request comes in to your application, an instance from the pool will handle the task/request.
Unlike your local machine, where request will be handled by your machine as well.
You may also find Google App Engine FAQ useful.
Not a lot. As you mentioned, you're currently on the SandBox (free) plan with GCP. At the moment this would deploy your MongoDB instance on
us-central1
region, and there's no other choice of region. There are also slight variation of RAM/Storage/Price between different cloud provider.You may be able to reduce network latency by choosing GAE on
us-central1
region as well.It's difficult to know for certain what is the issue without proper stack-trace or error log describing the timeout issue.
Commonly
node.js
project contain a JavaScript file calledconfig.js
which has a line below:Which basically trying to read configuration in the order of :
See also Google Cloud Platform: nodejs-getting-started
Also GoogleCloudPlatform/nodejs-docs-samples/appengine/mongodb project for an example.
I have had the same problem for a while but eventually this worked for me.Hope it helps.Ehen I read the the db connection details from a json file using nconf package as described by google https://cloud.google.com/community/tutorials/nodejs-mongodb-on-appengine with no mongoose I was able to solve it.Initially i was reading from env variables.
You dont have to use config.json as suggested by other answers.
Well this took me entirely too long, but the issue was with my Dockerfile.
I was extending the node.js runtime but my Dockerfile was missing lines to copy the app directory and install npm.
To create the appropriate Dockerfile I used the following command:
More information about the command and extending the node.js runtime can be found here.
My final Dockerfile after I added the dependencies I needed looks like this:
NOTE: I can only connect to my MongoDb instance after deployment. Running locally in Cloud Shell still times out.