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
Related
Good morning guys.
I'm having a problem connecting a nodejs application, in a container, to another container that contains a redis server. On my local machine I can connect the application to this redis container without any problem. However, when trying to upload this application in a container, a timeout error is returned.
I'm new to docker and I don't understand why I can connect to this docker container in the application running locally on my machine but that same connection doesn't work when I upload the application in a container.
I tried using docker-compose, but from what I understand it will upload in another container to the redis server, instead of using the redis container that is already in docker.
To connect to redis I'm using the following code:
createClient({
socket: {
host: process.env.REDIS_HOST,
port: Number(process.env.REDIS_PORT)
}
});
Where REDIS_HOST is the address of my container running on the server and REDIS_PORT is the port where this container is running on my server.
To run redis on docker I used the following guide: https://redis.io/docs/stack/get-started/install/docker/
I apologize if my problem was not very clear, I'm still studying docker.
You mentioned you are using Docker Compose. Here's an example showing how to start Redis in a container, and make your Node application wait for that container then use an environment variable in your Node application to specify the name of the host to connect to Redis on. In this example it connects to the container running Redis that I've called "redis":
version: "3.9"
services:
redis:
container_name: redis_kaboom
image: "redislabs/redismod"
ports:
- 6379:6379
volumes:
- ./redisdata:/data
entrypoint:
redis-server
--loadmodule /usr/lib/redis/modules/rejson.so
--appendonly yes
deploy:
replicas: 1
restart_policy:
condition: on-failure
node:
container_name: node_kaboom
build: .
volumes:
- .:/app
- /app/node_modules
command: sh -c "npm run load && npm run dev"
depends_on:
- redis
ports:
- 8080:8080
environment:
- REDIS_HOST=redis
So in your Node code you'd then use the value of process.env.REDIS_HOST to connect to the right Redis host. Here, I'm not using a password or a non-standard port, you could also supply those as environment variables that match the configuration of the Redis container in Docker Compose too if you needed to.
Disclosure: I work for Redis.
I'm currently working on an api.
When I run my api on my local computer I can connect to MongoDB but when I run it from the docker container, I cannot connect to MongoDB
I tried this to connect to the container :
mongodb://0.0.0.0:27018
and
mongodb://127.0.0.1:27018
I also check if the two containers can communicate together and they can so I don't know how to do it
There is my docker-compose
version: "3.9"
services:
api:
build:
context: .
dockerfile: Dockerfile
ports:
- "3001:3001"
volumes:
- .:/app
mongo:
container_name: "sell-mongodb"
image: mongo
ports:
- "27018:27017"
volumes:
- mongodb-data:/data/db/
volumes:
mongodb-data:
Use mongodb://mongo:27017.
Use mongo as hostname, because it is the name of your MongoDB service in Docker Compose. By default, Docker enables you to access other containers by this service hostnames.
Do not use 27018 port when connecting from within another container, as it is a port exposed to your host machine. Port 27017 on the other hand should be accessible by default from the internal docker network, i.e. from other containers.
See https://docs.docker.com/compose/compose-file/compose-file-v3/#ports
Docker file for my node app
FROM node:latest
COPY . .
RUN npm install
EXPOSE 5000
CMD ["npm", "start"]
docker compose file -
version: '3'
services:
pern-todo-backend:
image: pern-todo-backend
ports:
- 5000:5000
command: bash -c 'while !</dev/tcp/db/5432; do sleep 1; done; npm start'
depends_on:
- db
environment:
- DATABASE_URL=postgres://postgres:*****#db:5432/pern
- PORT=5000
db:
image: postgres
ports:
- 5432:5432
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=****
- POSTGRES_DB=pern
when i try to hit the endpoint from postman -
{
"errno": -111,
"code": "ECONNREFUSED",
"syscall": "connect",
"address": "172.26.0.3",
"port": 5432
}
I tried updating my pg pool hostname as the name of my container also
const pool = new Pool({
user : 'postgres',
password : 'subh1994',
host : 'localhost',
port : 5432,
database : 'pern'
})
I'm new with Docker , please help . thanks
Can you check your container name of db service by docker ps
It can be different than service name (db), you can try replacing it in DATABASE_URL connection string.
But one weird thing is db is getting resolved to 172.26.0.3 if the db is correct container name then you can try checking logs by docker logs db to get details on what might be wrong.
On side note if you don't want datbase exposed to host you can skip the ports mapping in db service.
By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.
https://docs.docker.com/compose/networking/
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
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).