Connection nodejs and mongo with docker - node.js

This is my docker-compose-file:
version: "2"
services:
rest-api:
build: .
ports:
- "3007:3007"
links:
- mongo
mongo:
image: mongo
volumes:
- /data/mongodb/db:/data/db
ports:
- "27017:27017"
This is my Dockerfile:
FROM mhart/alpine-node:latest
RUN rm -rf /tmp/node_modules
ADD package.json /tmp/package.json
RUN cd /tmp && npm install
RUN mkdir -p /opt/app && cp -a /tmp/node_modules /opt/app/
WORKDIR /opt/app
ADD . /opt/app
EXPOSE 3007
CMD ["node", "index.js"]
When I run the image, node is not able to connect to mongo:
MongoError: failed to connect to server [localhost:27017] on first connect
What can be wrong? How can I debug this?
Update:
In my node app I have:
let connection = mongoose.connect('mongodb://localhost/myapp');

Node is trying to connect to Mongo on localhost, which fails because it is not running in the same container as Node. Instead, it runs in a different container, i.e. on a different host.
You probably have a line like this in your application:
var url = 'mongodb://localhost:27017/myproject';
It defines where the MongoDB is located. You need to change localhost to the actual host, which in your case would be mongo.

In your node app you need to reference your container instead of localhost.
In your connection string to mongo use the name mongo as the host you are probably just using the default at the minute
https://docs.mongodb.com/manual/reference/connection-string/
e.g.
mongodb://mongo:27017/
You need to do this because the mongo database is in a separate container (with a different IP address) they are linked via TCP so localhost relates to the container node is in.

Related

Can't connect to MongoDB on Docker Container

I'm working on a node js api and I'm using mongodb. Right now I'm facing one problem when I try to connect to the database, I'm getting this error MongooseServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017 the api is running on a docker container and the database is local, I'm not running mongo on docker container.
this is my connection string mongodb://localhost:27017/database
and this is my docker file
FROM node
RUN apk add dumb-init
ENV PORT=4000
WORKDIR /usr/src/app
COPY package-lock.json /usr/src/app/
RUN npm ci
COPY . /usr/src/app/
USER node
EXPOSE 4000
CMD ["dumb-init", "node", "/usr/src/app/app.js"]
UPDATE
Forgot to add the docker-compose.yml
Here it is:
version: '2.1'
services:
api:
build:
context: .
dockerfile: ./Dockerfile.api
ports:
- "4000:4000"
- "27017:27017"
extra_hosts:
"host.docker.internal": host-gateway
volumes:
- ./var/:/var
restart: on-failure
Can someone tell what is wrong or what else is missing?
Make the hostname for your connection string to mongodb
host.docker.internal instead of localhost
i.e: mongodb://host.docker.internal:27017/database
https://docs.docker.com/desktop/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host

Docker MongoDB immadiately closes connection after receiving metadata

I'm trying to compose docker app with two containers:
mongo
app
Mongo container works just fine, meanwhile app cannot connect to mongo. Neither node.js app nor mongostat can. The weird part is, I tried to run this project on both computers with Win10 and it works normally on the other one.
These are logs from mongo container when I run node app.js or mongostat --uri "mongodb://mongo:27017/project" from app container:
2019-05-22T09:33:52.225+0000 I NETWORK [conn17] received client metadata from 192.168.96.2:42916 conn17: { driver: { name: "nodejs", version: "3.1.10" }, os: { type: "Linux", name: "linux", architecture: "x64", version: "4.9.125-linuxkit" }, platform: "Node.js v10.15.3, LE, mongodb-core: 3.1.9" }
2019-05-22T09:33:52.231+0000 I NETWORK [conn17] end connection 192.168.96.2:42916 (0 connections now open)
This means both containers can see each other so .yml file should be fine. If the problem was with code then it shouldn't work on both computers.
Dockerfile:
FROM node:10.15.3-alpine
RUN apk update && apk --no-cache --virtual build-dependencies add python make g++ && apk del build-dependencies
RUN mkdir -p /home/node/app && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
COPY --chown=node:node . .
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
RUN npm install
EXPOSE 3000
CMD ["node", "app.js"]
docker-compose.yml:
version: "3.5"
services:
app:
container_name: app
restart: always
build: .
ports:
- "3000:3000"
networks:
- mongo
mongo:
restart: always
container_name: mongo
image: mongo
expose:
- 27017
volumes:
- mongodata:/data/db
ports:
- '27017:27017'
networks:
- mongo
volumes:
mongodata:
networks:
mongo:
external: true
snippet from app.js:
MongoClient.connect('mongodb://mongo:27017/project', {useNewUrlParser: true}, (err, client) => {
if (err) throw err; //throws MongoNetworkError: failed to connect to server [mongo:27017] on first connect [MongoNetworkError: getaddrinfo ENOTFOUND mongo mongo:27017]
console.log("connected");
client.close();//at the moment this line is not being reached because of throw err;
});```
Does it help if you insert a "sleep 10" in your application, before connecting to the mongo db? If so, adding something like wiatforit (https://github.com/maxcnunes/waitforit) might help.
Since you are getting a getaddrinfo ENOTFOUND error, the mongo hostname isn't resolving. Usually, that happens for one of two reasons: 1) your containers aren't on the same network or 2) the other container isn't up and running yet. Seeing that they are on the same network, it sounds like it's something with the container being up.
To troubleshoot, I would start another container, put it on the network, and validate the mongo hostname resolves.
docker container run --rm -ti --network mongo ubuntu
$ apt update && apt install -y dnsutils
$ dig mongo
At this point, you should see the A record resolve to the database. If not, validate the mongo database container is up and running.
You can also try doing this within your app container as well. If that's working, then using something like waitforit should work. This is a common issue, as apps may start up before the database is either running or ready to accept connections.
As one other item of feedback, you don't need to expose the mongo port. This is making it accessible to the world, which most likely isn't what you want. You can still do container-to-container communication without exposing the port.
After hours of trying multiple things I have found solution: turn off Windows Firewall. That's it.
Thanks, I appreciate your help.

Nodejs application docker unable to connect to mongodb docker container

I have a nodejs application which dockerized and need a replicated MongoDB database. I have built my replicated MongoDB in docker-compose and working just fine. if I run the command docker inspect MongoDB-primary |grep IPAddress its print:
"IPAddress": "",
"IPAddress": "172.18.0.2",
now in my application, i give this ip as mongoconnection string(of course with protocol names) but the application cannot connect to MongoDB and throw this error message(application also is a docker container):
message: 'failed to connect to server [172.18.0.2:27017] on first connect [MongoNetworkError: connection 1 to 172.18.0.2:27017 timed out]',
here is my mongodb docker compose file:
version: '2'
services:
mongodb-primary:
image: 'bitnami/mongodb:latest'
environment:
- MONGODB_REPLICA_SET_MODE=primary
volumes:
- 'mongodb_master_data:/bitnami'
mongodb-secondary:
image: 'bitnami/mongodb:latest'
depends_on:
- mongodb-primary
environment:
- MONGODB_REPLICA_SET_MODE=secondary
- MONGODB_PRIMARY_HOST=mongodb-primary
- MONGODB_PRIMARY_PORT_NUMBER=27017
mongodb-arbiter:
image: 'bitnami/mongodb:latest'
depends_on:
- mongodb-primary
environment:
- MONGODB_REPLICA_SET_MODE=arbiter
- MONGODB_PRIMARY_HOST=mongodb-primary
- MONGODB_PRIMARY_PORT_NUMBER=27017
volumes:
mongodb_master_data:
driver: local
and my node js application dockerfile is:
FROM node:6.0
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm#5+)
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm install --only=productio
# Bundle app source
COPY . .
EXPOSE 3001
CMD [ "npm", "start" ]
how can I fix this?
Your docker-compose does not automatically expose tcp ports to the outer world, like your host PC (I assume your nodeJs runs on host and not included in docker-compose). This is the behavior of docker bridge networks, you can read more at https://docs.docker.com/network/bridge/
You have to do one of the following:
Include your NodeJs container into docker-compose
or
Expose ports from docker-compose.yml
I had the same issue and adding the ports fixed it for me.
Make sure your connection url includes the image name:
mongodb://mongo:27017/ and not localhost.
mongo:
image: mongo
expose:
- 27017
ports:
- "27017:27017"
volumes:
- ./data/db:/data/db

mongoose connection failure using docker-compose

I have a Node express server consuming a Mongo database.
I'm trying to create a container for each of them using docker-compose.
Here's my docker-compose.yml file:
version: "2"
services:
server:
container_name: server
restart: always
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
container_name: db
image: mongo
volumes:
- /var/lib/mongodb:/data/db
ports:
- "27017:27017"
And my Dockerfile:
FROM node:latest
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app
RUN npm install
COPY . /usr/src/app
RUN npm run build-run
EXPOSE 3000
I saw on many tutorials that, when using Docker to create a Mongo container, the connection string should be updated in mongoose.connect to use Docker containers naming resolution.
So I changed my connection string according to my docker-compose file:
private readonly CONNECTION_STRING: String = 'mongodb://db/search-people-db'
public connect(): void {
mongoose.connect(this.CONNECTION_STRING)
this._db.on('error', (err) => {
console.log(`mongoose server failed to start: ${err}`)
})
this._db.once('open', () => {
console.log(`mongoose server running using ${this.CONNECTION_STRING}`)
})
}'
However, when running sudo docker-compose up, I keep getting the following error:
Mongoose server failed to start: MongoNetworkError: failed to connect to server [db:27017] on first connect [MongoNetworkError: getaddrinfo ENOTFOUND db db:27017]
What am I doing wrong ? Thanks in advance
MongoDB's container boots up but MongoDB itself needs more time start. so your application will not connect to it until it's fully started.
as Docker's documents suggested, you should set a wait time for your application and then run your code.
I suggest to make mongoose try to reconnect if couldn't connect at the first time or let the application crash if it couldn't connect. Docker will run your container again.
Replace depends_on with links in your docker-compose.yml and try to run command again.

Exposing docker container on local server

I have a nodejs-mongo db app that is running inside docker containers.
I can access it on localhost etc...
But now I would like to install/deploy these containers on a local server, so that I can access this application outside my network.
Please note my server is Ubuntu 16.04.1 LTS (xenial)
Also I would like to access Db from outside, so that I can send data to the Db using custom script.
I am newbie in both networking and Docker. As a result I am struggling to understand what needs to be done. Any pointers would be appreciated
Here is the docker-compose.yml
version: "2"
services:
web:
build: .
volumes: # Use this to mount app from local disk
- ./:/usr/src/app
ports:
- "8080:8080"
- "5858:5858"
entrypoint: node --debug=5858 app.js
links:
- mongo
mongo:
image: mongo
ports:
- "27017:27017"
Here is my Dockerfile
FROM node:argon
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
# Bundle app source
COPY . /usr/src/app
EXPOSE 8080
CMD [ "npm", "start" ]
Usual command that I give to start my containers docker-compose up --build -d
Here is docker ps result
"node --debug=5858 ap" 13 minutes ago Up 13 minutes 0.0.0.0:5858->5858/tcp, 0.0.0.0:8080->8080/tcp nodemongochart_web_1
"/entrypoint.sh mongo" 13 minutes ago Up 13 minutes 0.0.0.0:27017->27017/tcp nodemongochart_mongo_1
If by local server, you mean your own machine at home, you will need to do something called "Port Forwarding".
It's usually configurable in your router, and you'll be able to access your application via some kind of link like this :
http://you-personal-ip:8080
If you'll be using another host, not in your own network, they should provide you with an IP address, in that case, no need for port forwarding.

Resources