Cannot connect to MongoDB via node.js in Docker - node.js

My node.js express app cannot connect to the MongoDB in a Docker. I'm not that familiar with Docker.
node.js connection:
import mongodb from 'mongodb';
...
mongodb.MongoClient.connect('mongodb://localhost:27017', ... );
Dockerfile:
FROM node:argon
RUN mkdir /app
WORKDIR /app
COPY package.json /app
RUN npm install
COPY . /app
EXPOSE 3000
CMD ["npm", "start"]
docker-compose.yml
version: “2”
services:
web:
build: .
volumes:
— ./:/app
ports:
— “3000:3000”
links:
— mongo
mongo:
image: mongo
ports:
— “27017:27017”
Build command: docker build -t NAME .
Run command: docker run -ti -p 3000:3000 NAME
Connection error:
[MongoError: failed to connect to server [localhost:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]]
name: 'MongoError',
message: 'failed to connect to server [localhost:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]'

Try:
mongodb.MongoClient.connect('mongodb://mongo:27017', ... );
Change your docker-compose.yml:
version: "2"
services:
web:
build: .
volumes:
- ./:/app
ports:
- "3000:3000"
links:
- mongo
mongo:
image: mongo
ports:
- "27017:27017"
And use some docker compose commands:
docker-compose down
docker-compose build
docker-compose up -d mongo
docker-compose up web

Try this.
When using linked docker containers you should use the name of the container in this case for example your connection to mongodb should be mongodb.MongoClient.connect('mongodb://mongo:27017', ... ); instead of mongodb.MongoClient.connect('mongodb://localhost:27017', ... );. The reason for changing it to mongo is because you used the links attribute to mongo in your docker-compose.yml. That would result to a hostname of mongo in your /etc/hosts of the web docker container. Reference linking-containers.
The docker-compose.yml seems to be lacking an indention. On the mongo attribute should be the same level as web.
version: '2'
services:
web:
build: .
volumes: ['./:/app']
ports: [ '3000:3000' ]
links: [ mongo ]
mongo:
image: mongo
ports: [ '27017:27017' ]
I tried your configuration using my docker what Ive done is update docker-compose.yml then I docker-compose build then docker-compose up. Logs of my local run

I am not sure if you still have this question, but the datasources.json should be:
"host": "mongo"
rather than "localhost".
In my logs I see:
mongo | NETWORK [listener] connection accepted from 172.22.0.3:47880 #1 (1 connection now open)
As you can see, docker compose will NAT mongo to another V-LAN. The IP address 172.22.0.0 is an internal IP address used by the daemon to route a docker-compose image. So localhost is now not in the game.
At least, it works for me.
datasources.json
"mongoDS": {
"host": "mongo",
"port": 27017,
...

in my case works like this :
just link to the container from the command line. db is my up database container
sudo docker run -it --link db:db1 --publish 4000-4006:4000-4006 --name backend backend:latest

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

Cant reach mongo db container

I trying to implement a dockerized mongo/node based app by this article.
docker-compose.yml
version: '3'
services:
gecar_app:
build:
context: .
dockerfile: Dockerfile.gecars
restart: always
ports:
- 3000:3000
depends_on:
- mongo
command: /usr/app/initAndStartService.sh
mongo:
container_name: mongo
image: mongo
volumes:
- ./data:/data/db
ports:
- "27017:27017"
Dockerfile.gercars
FROM node:latest
RUN mkdir -p /usr/app
WORKDIR /usr/app
COPY src/ /usr/app/src/
COPY package.json /usr/app/package.json
COPY webpack.config.js /usr/app/webpack.config.js
COPY tsconfig.json /usr/app/tsconfig.json
COPY initAndStartService.sh /usr/app/initAndStartService.sh
RUN yarn
RUN yarn build
RUN ["chmod", "+x", "/usr/app/initAndStartService.sh"]
initAndStartService.sh
#!/bin/sh
curl 127.0.0.1:27017
but when run docker-compose up get this:
mongo | 2019-11-19T06:13:21.682+0000 I NETWORK [initandlisten] Listening on 0.0.0.0
mongo | 2019-11-19T06:13:21.683+0000 I NETWORK [initandlisten] waiting for connections on port 27017
...................
gecar_app_1 | Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0curl: (7) Failed to connect to 127.0.0.1 port 27017: Connection refused
If I recognize the situation correctly, gecar_app_1 container cant reachmongo` container.
depends_on
Express dependency between services, Service dependencies cause the
following behaviors:
docker-compose up starts services in dependency order. In the following example, db and redis are started before web.
docker-compose up SERVICE automatically includes SERVICE’s dependencies. In the following example, docker-compose up web also
creates and starts db and redis.
docker-compose stop stops services in dependency order. In the following example, web is stopped before db and redis.
in other words, when you want to communicate with the mongo container, all you have to do is to call it as mongo based on your container service naming.
So curl mongo:27017 from the gecar_app container will do the trick
127.0.0.1 is a loopback address, this mean, when you run curl 127.0.0.1:27017 on gecar_app container, you try to connect to itself, but gecar_app did not have any service running on 27017 port. What you need to connect is mongo service (I think so).
You use depends_on to wait until the mongo service started, then start the gecar_app container (good point), now mongo will be come to a hostname, and gecar_app can connect to mongo via mongo "domain".
But, gecar_app maybe started before mongodb service already, then you have make sure that when mongo service already. You can use healthcheck property to do that.
Finally,
docker-compose.yml
version: '3'
services:
gecar_app:
build:
context: .
dockerfile: Dockerfile.gecars
restart: always
ports:
- 3000:3000
depends_on:
- mongo
command: /usr/app/initAndStartService.sh
mongo:
container_name: mongo
image: mongo
volumes:
- ./data:/data/db
ports:
- "27017:27017"
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongo mongo:27017/test --quiet 1
interval: 3s
timeout: 5s
retries: 5
and, initAndStartService.sh
#!/bin/sh
curl mongo:27017

How to connect graphql and prisma in docker containers?

I am trying to build a docker-compose file that run a node.js graphql api that uses prisma and mongodb.
But I got an error request to http://localhost:4466/ failed, reason: connect ECONNREFUSED 127.0.0.1:4466 when ever I try to send requests from graphql playground and the same error when I run prisma deploy or just try to ping http:localhost:4466 from inside the graphql container.
I have tried to use the default network and creating new network but I got the same error.
I have tried to use links (which is deprecated) in version 3 but also I got the same error.
P.S I can open the playground of prisma normally in the browser with the link: http://localhost:4466
This is my docker-compose file:
version: '3'
services:
web:
build: .
networks:
net:
ports:
- "80:4000"
command: wait-for-it/wait-for-it.sh http://localhost:4466 -t 30 -- ./run.sh
prisma:
image: prismagraphql/prisma:1.34
restart: always
networks:
net:
ports:
- "4466:4466"
environment:
PRISMA_CONFIG: |
port: 4466
# uncomment the next line and provide the env var PRISMA_MANAGEMENT_API_SECRET=my-secret to activate cluster security
# managementApiSecret: my-secret
databases:
default:
connector: mongo
uri: mongodb://prisma:prisma#mongo
command: /bin/sh.sh
mongo:
image: mongo:3.6
restart: always
networks:
net:
environment:
MONGO_INITDB_ROOT_USERNAME: prisma
MONGO_INITDB_ROOT_PASSWORD: prisma
ports:
- "27017:27017"
volumes:
- mongo:/var/lib/mongo
volumes:
mongo:
networks:
net:
And this is the dockerfile of the web service:
FROM node:10
WORKDIR /app
COPY . /app/
RUN yarn install --pure-lockfile
RUN yarn global add prisma
And this is the run.sh file:
echo "prisma deploy command "
prisma deploy
echo "get-schema command"
yarn run get-schema
echo "starting command"
yarn run start
Are there anything that I misunderstand, Or what I need to fix to make it work?
You should use http://prisma:4466 as the connection URL in your web container. As your containers will be connected to the same network the name of the container will be DNS name and therefor will be resolved to IP of concrete container.
The localhost in your Node application points to the container running Node itself, not your host machine. Replace http://localhost:4466 with http://prisma:4466 or http://<host-machine-local-ip>:4466
To get host IP on a Unix machine run:
hostname -i
Or
ifconfig | awk '/broadcast/ {print $2}'
Change the content of your prisma.yml from
endpoint: http://localhost:4466
datamodel: datamodel.prisma
to
endpoint: http://192.168.99.100:4466
datamodel: datamodel.prisma
This worked for me.
Run your docker container by typing $docker-compose up -d -d flag is for running container in detach mode.
Instead of using endpoint as http://localhost:4466 use http://127.0.1.1:4466 Or check your localhost by the cmd: $localhost -i.
In prisma-binding your constructor should have endpoint as http://127.0.1.1:4466.
const prisma = new Prisma({
typeDefs: './src/generated/prisma.graphql',
endpoint: 'http://127.0.1.1:4466'
});

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.

Resources