Docker container unable to connect to mongo hosted on locally - python-3.x

I am trying to connect from a docker container (docker daemon running in rootless mode) to a mongo DB instance (hosted in the main host as a sudo systemctl service). The way I am trying to connect is by running
docker run --network="host" image:1.0.0
In my python script inside the docker I connect by below method:
import pymongo
from pymongo import MongoClient
connection = pymongo.MongoClient('127.0.0.1', 27017)
db = connection['test']
list_of_collections = db.list_collection_names()
My docker version: 20.10.14
Mongo DB version : 5.0.6
Pymongo version:3.11.4
Host: ubuntu-20.04
My mongo host config is like the below:
net:
port: 27017
bindIp: 0.0.0.0
The error returned from the docker container is as below :
pymongo.errors.ServerSelectionTimeoutError: 127.0.0.1:27017: [Errno 111]
Connection refused,Timeout 30s
Any help to resolve this would be appreciated.

Related

Node app fails to connect to MongoDB, but only in Docker

I have two apps:
MongoDB (started from the Bitnami MongoDB Docker image)
My custom node app
The two apps interact flawlessly when my node app is run natively. Now I've put it inside a Docker container and when I start both together with docker compose up, the backend can not connect to MongoDB.
This is an excerpt of the startup sequence:
mongodb_1 | 2018-11-10T22:22:52.481+0000 I NETWORK [initandlisten] waiting for connections on port 27017
[...]
backend_1 | 2018-11-10T22:23:48.119Z 'MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]'
This is my docker-compose.yml:
version: '2'
services:
mongodb:
image: bitnami/mongodb:latest
expose:
- 27017
environment:
- ALLOW_EMPTY_PASSWORD=yes
backend:
build: ./backend
environment:
API_HOST: http://localhost:3000/
APP_SERVER_PORT: 3000
expose:
- 3000
volumes:
- ./backend:/app/backend
links:
- mongodb
depends_on:
- mongodb
This is my node call to the DB:
mongoose.connect('mongodb://localhost:27017/groceryList', {
useNewUrlParser: true
});
I skimmed about 15 Stackoverflow questions asking the same and I am not getting the cause:
It is not that MongoDB is not ready when my node app tries to
connect. I wrapped my connection call into an auto reconnection
function as described here and the error repeats endlessly. It is not just about the "first
connect".
I can publish Port 27017 of the MongoDB container and
happily connect with Robo3T. The DB is definitely working.
When I connect to mongodb://mongo:27017/groceryList instead, the same applies, only with the ENOTFOUND flag instead of ECONNREFUSED.
What am I missing?
Docker 18.06.1-ce
docker-compose 1.22.0
Mongoose 5.3.6
MongoDB 4.0.3
Node 11.1.0
macOS 10.14.1
Your mongodb service is named mongodb not mongo.
Try
mongoose.connect('mongodb://mongodb:27017/groceryList', {
useNewUrlParser: true
});
The generic form is 'mongodb://mongoServiceName:27017/dbname', this uses docker's automatic dns resolution for containers within the same network.
And as you may already know from other questions/answers, within a container, the url is relative to itself, therefore since there not mongodb running inside the backend container, it can't connect to it.
It's not possible to use localhost:27017 into a container to communicate with other because the scope "localhost" is self refering (localhost:27017 will look for the port 27017 into the container backend - not in mongodb container)
Then, you ned to put or the service name (mongodb) or IP of your machine

Docker can't connect to redis from another service

I can't figure out how to connect to my redis service from my app service. Using DDocker version 18.03.1-ce, build 9ee9f40ocker for Mac.
I've tried connecting the various ways I've found on similar questions:
const client = redis.createClient({ host: 'localhost', port: 6379});
const client = redis.createClient({ host: 'redis', port: 6379});
const client = redis.createClient('redis://redis:6379');
const client = redis.createClient('redis', 6379); // and reversed args
I always get some form of:
Error: Redis connection to localhost:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
Error: Redis connection to redis:6379 failed - connect ECONNREFUSED 172.20.0.2:6379
Docker containers
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0fd798d58561 app_app "pm2-runtime start e…" 2 seconds ago Up 7 seconds app
65d148e498f7 app_redis "docker-entrypoint.s…" About a minute ago Up 8 seconds 0.0.0.0:6379->6379/tcp redis
Redis works:
$ docker exec -it redis /bin/bash
root#65d148e498f7:/data# redis-cli ping
PONG
Redis Dockerfile (pretty simple)
FROM redis:4.0.9
COPY redis.conf /usr/local/etc/redis/redis.conf
CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]
app Dockerfile
FROM node:10.3.0-slim
RUN mkdir -p /app
COPY src/* /app/
CMD ["pm2-runtime", "start", "/app/ecosystem.config.js"]
docker-compose.yml
version: "3"
services:
redis:
build: ./redis/
container_name: redis
restart: unless-stopped
ports:
- "6379:6379"
expose:
- "6379"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- 'API_PORT=6379'
- 'NODE_ENV=production'
app:
depends_on:
- redis
build: ./app/
container_name: app
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /app/node_modules
environment:
- 'NODE_ENV=production'
It looks like your redis image is configured to listen on 127.0.0.1 rather than all interfaces. This is not an issue with the default redis images, so either use the official image from docker hub, or correct your configuration to listen on 0.0.0.0.
You'll be able to verify this with netshoot:
docker run --rm --net container:app_redis nicolaka/netshoot netstat -ltn
In the redis conf, listening on all interface is done by commenting out the "bind" line in redis.conf.
Let me explain it in simple language. When you run docker-compose up it runs redis and app in separate containers. Now your app needs to connect/access the redis container (remember redis is not at your machines localhost, its inside a container and runs inside it at default port 6379). By default Docker will keep app container and redis container in same network and you can access a container by its service name (which in your case is redis and app) so in order to access redis from app container all you need is to use the default port 6379 and host will be the service name (in your case "redis").
For a node application running in a container get access to Redis (which was also running in a container) by
const redis = require("redis");
const client = redis.createClient(6379, "service-name-for-redis-container");
I solve this problem changing the redis host from 'localhost' to 'redis', exemple:
REDIS_HOST=redis
REDIS_PORT=6379
After the change my docker service started to comunicate with redis.
Original forum answer: https://forums.docker.com/t/connecting-redis-from-my-network-in-docker-net-core-application/92405
In my case the problem was that I was binding a different port on redis:
redis:
image: redis
ports:
- 49155:6379
And I was trying to connect to port 49155 but I needed to connect through port 6379 since the connection is from another service.
localhost from the app container's perspective won't be able to leave the app container. So the best bet is to use redis or the host's ip address.
If you want to reach redis from the app container, you'll need to link them or put them into the same network. Please add a network property to both services, using the same network name. Docker will then provide you with with valid dns lookups for the service names.
See the official docs at https://docs.docker.com/compose/compose-file/#networks (for the service: property) and https://docs.docker.com/compose/compose-file/#network-configuration-reference (for the top-level networks property).

I can't connect to my mongo docker container by its name

I'm pretty new to docker but I'm having some issues getting a node app to connect to a mongo database running on a separate container.
I'm using the official mongo image
I run it using:
docker run --name some-mongo --network-alias some-mongo -d mongo
It's running on port 27017 by default. I can connect to it using the mongo shell:
mongo --host mongodb://172.17.0.2:27017
But I can't connect to it by name
mongo --host mongodb://some-mongo:27017
MongoDB shell version: 3.2.19
connecting to: mongodb://some-mongo:27017/test
2018-05-07T17:23:20.813-0400 I NETWORK [thread1] getaddrinfo("some-mongo") failed: Name or service not known
2018-05-07T17:23:20.813-0400 E QUERY [thread1] Error: couldn't initialize connection to host some-mongo, address is invalid :
connect#src/mongo/shell/mongo.js:223:14
#(connect):1:6
exception: connect failed
Instead I get an error message about how I can't connect to the mongo host:
I'm trying some docker-compose tutorials but either they're too simple or they don't seem to work for me. I just want to connect a custom node app, (not the official node) to mongodb and some other dependencies.
Your approach is not altering your host's system configuration, so that the mongo service will not be available just like that. Agreeing with #unm4sk, you should compose you application's services into a single compose file like this:
version: '2'
services:
mongo:
image: mongo
expose:
- "27017"
[...]
service_utilizing_mongo:
[...]
links:
- mongo:mongo
Then, your service_utilizing_mongo would have a DNS entry that'd make this service capable of accessing your mongo service via a alias mongo on a default 27017 port.
You have to run your container with passing ports to your host machine:
docker run -p 27017:27017 --name some-mongo --network-alias some-mongo -d mongo
Then you can connect to MongoDB from your host machine:
If you don't want to do this you can connect to mongo through docker container command
docker exec -it some-mongo mongo

Cannot Connect to Postgres db between docker compose services

I am trying to connect postgresdb service with nodejs web service using docker compose
My docker-compose.yml file
version: "3"
services:
web:
build: ./
ports:
- "40000:3000"
depends_on:
- postgres
postgres:
image: kartoza/postgis:9.6-2.4
restart: always
volumes:
- postgresdata:/data/db
environment:
- POSTGRES_PASS=password
- POSTGRES_DBNAME=sticki
- POSTGRES_USER=renga
- ALLOW_IP_RANGE=0.0.0.0/0
ports:
- "1000:5432"
volumes:
postgresdata:
So when i do docker-compose up in my root directory both services are running and i can access web service using localhost:40000 and postgres service using postico on localhost:1000
But in Node Web service i have written code to access postgres using Sequelize as
const sequelize = new Sequelize('sticki', 'renga', 'password', {
host: 'postgres',
dialect: 'postgres',
});
But I get the following error
SequelizeConnectionRefusedError: connect ECONNREFUSED 172.18.0.2:1000
Why does postgres Connection is made to 172.18.0.2 instead of localhost(0.0.0.0)? What i am doing wrong?
For your web container postgres is a DNS name defined in compose as a service. It fetches the postgres DNS IP address via docker internal DNS & network, that's why it's resolving to 172.18.0.2. If you go to web container & ping postgres, you will get the same IP.
As a fix, configure your node service to connect to host postgres on port 5432 since it's the container port. Port 1000 is the host machine port, if you want to use port 1000, configure node service to connect to your MACHINE_IP:1000.
PS - Localhost within a container means the container itself & nothing else.
Service name is taken from container_name - which is fixed. In your case you do not have that and name is created from folder where docker-compose.yml is + _ + service name + _1.
With this DNS name you can reach your service on the default network that docker-compose will create, from one service to reach the other.
Thanks

Seeding data in a Mongo db within a linked Docker container

I'm using fig to deploy my Node.js app.
fig.yml
web:
build: .
command: node app.js
links:
- db
ports:
- "1337:1337"
db:
image: dockerfile/mongodb
Running fig run db env gives me the following environment vars:
DB_PORT=tcp://172.17.0.29:27017
DB_PORT_27017_TCP=tcp://172.17.0.29:27017
DB_PORT_27017_TCP_ADDR=172.17.0.29
DB_PORT_27017_TCP_PORT=27017
DB_PORT_27017_TCP_PROTO=tcp
DB_PORT_28017_TCP=tcp://172.17.0.29:28017
DB_PORT_28017_TCP_ADDR=172.17.0.29
DB_PORT_28017_TCP_PORT=28017
DB_PORT_28017_TCP_PROTO=tcp
DB_NAME=/pos_db_run_3/db
My app's Dockerfile looks like this
# Pull base image.
FROM dockerfile/nodejs
# install mongo client
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
RUN echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | tee /etc/apt/sources.list.d/mongodb.list
RUN apt-get update
RUN apt-get install -y dnsutils
RUN apt-get install -y mongodb-org-shell
# copy the source files into the image
COPY . /data/myapp
# Define working directory.
WORKDIR /data/myapp
# Install dependencies
RUN npm install
# Create default database and user
RUN mongo $DB_PORT < seed-mongo
RUN node/seed.js
EXPOSE 1337
# Define default command.
CMD ["bash"]
However the build is failing at RUN mongo $DB_PORT < seed-mongo
MongoDB shell version: 2.6.5
connecting to: test
2014-11-20T20:47:59.193+0000 warning: Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
2014-11-20T20:47:59.195+0000 Error: couldn't connect to server 127.0.0.1:27017 (127.0.0.1), connection attempt failed at src/mongo/shell/mongo.js:146
exception: connect failed
Service 'web' failed to build: The command [/bin/sh -c mongo $DB_PORT < seed-mongo] returned a non-zero code: 1
According to the fig docs I'd be better off referring to the database simply as db so I tried
RUN mongo db < seed-mongo
But this gave me
MongoDB shell version: 2.6.5
connecting to: db
2014-11-20T21:08:11.154+0000 warning: Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
2014-11-20T21:08:11.156+0000 Error: couldn't connect to server 127.0.0.1:27017 (127.0.0.1), connection attempt failed at src/mongo/shell/mongo.js:146
exception: connect failed
So I injected a RUN host db in there just to see if db really is a host name. And no, despite the docs above it's not.
Step 10 : RUN host db
---> Running in 73b4dc787c79
Host db not found: 3(NXDOMAIN)
Service 'web' failed to build: The command [/bin/sh -c host db] returned a non-zero code: 1
So I'm stumped.
How am I supposed to talk to the mongo instance running in my linked Docker container?
Your mongo container has ip address $DB_PORT_27017_TCP_ADDR
So try with mongo --host $DB_PORT_27017_TCP_ADDR < seed-mongo
You can't use it in a RUN statement I think, because the environment variables are not available at build-time. You could try using it in a CMD I guess.
My solution was a combination of insights from above, but mainly I stopped trying to seed a specific database and db user in the build phase and instead use --host db_1 with no username or password. If I really need that functionality later I'll work it out.
I could then build the project and connect it to mongo in the other image.
In my config/connections.js I included:
development: {
adapter : 'sails-mongo',
host : 'db_1',
port : 27017,
user : '',
password : '',
database : process.env.DB_NAME
},
and I changed the CMD to be "node data/seeds.js && node app"
You never exposed your Mongo port.
web:
build: .
command: node app.js
links:
- db
ports:
- "1337:1337"
db:
image: dockerfile/mongodb
ports:
- "27017:27017"

Resources