Tuesday, November 2, 2021

[SOLVED] Node js cant connect to Redis Docker Centos 7

Issue

I have docker compose use Mongo, Redis and Node js. Mongo and Redis running good the problem is node js cant connect to Redis.

When i test on my ubuntu laptop with docker is work fine. but not when i run docker in server (Centos 7).

i sure my redis work because when i do SSH Port Forwarding its work. i can access from my ubuntu.

version: '2.1'

services:
  aqua-server:
    image: aqua-server
    build: .
    command: pm2-runtime process.yml
    container_name: "aqua-server"
    working_dir: /app
    environment:
      NODE_ENV: production
      AQUA_MONGO_IP: 172.20.0.1
      AQUA_MONGO_PORT: 3002
      AQUA_MONGO_DATABASE: aqua-server
      AQUA_EXPRESS_PORT: 3000
      AQUA_REDIS_PORT: 3003
      AQUA_REDIS_HOST: 172.20.0.1
    volumes:
      - .:/app/
    ports:
      - 3001:3000
    links:
      - mongodb
      - redis
    depends_on:
      - mongodb
      - redis
    networks: 
      frontend:
        ipv4_address: 172.20.0.2
  mongodb:
    image: mongo:4.2.0-bionic
    container_name: "aqua-mongo"
    environment:
      MONGO_LOG_DIR: /dev/null
    volumes:
      - /home/sagara/DockerVolume/MongoLocal:/data/db
    ports:
      - 3002:27017
    networks: 
      frontend:
        ipv4_address: 172.20.0.3
  redis:
    image: redis:5.0.5-alpine
    container_name: "aqua-redis"
    ports:
      - 3003:6379
    networks: 
      frontend:
        ipv4_address: 172.20.0.4
networks: 
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24

This my DockerFile on Node js

FROM node:10.16.0-alpine

WORKDIR /app

COPY . .

RUN npm install
RUN npm install pm2 -g

EXPOSE 3000

CMD pm2-runtime process.yml

this proccess.yml

apps:
  - script: index.js            
    instances: 1                    
    exec_mode: cluster             
    name: 'aqua-server'

this my logs docker

aqua-server    | Error: Redis connection to 172.20.0.1:3003 failed - connect EHOSTUNREACH 172.20.0.1:3003
aqua-server    |     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1106:14)
aqua-server    | 2019-09-06T07:48:13: PM2 log: App name:aqua-server id:0 disconnected
aqua-server    | 2019-09-06T07:48:13: PM2 log: App [aqua-server:0] exited with code [0] via signal [SIGINT]
aqua-server    | 2019-09-06T07:48:13: PM2 log: App [aqua-server:0] starting in -cluster mode-
aqua-server    | 2019-09-06T07:48:13: PM2 log: App [aqua-server:0] online

Redis Logs Docker

aqua-redis     | 1:M 06 Sep 2019 07:47:12.512 * DB loaded from disk: 0.000 seconds
aqua-redis     | 1:M 06 Sep 2019 07:47:12.512 * Ready to accept connections

Mongo Logs Docker

aqua-mongo     | 2019-09-06T07:47:15.895+0000 I  NETWORK  [initandlisten] Listening on /tmp/mongodb-27017.sock
aqua-mongo     | 2019-09-06T07:47:15.895+0000 I  NETWORK  [initandlisten] Listening on 0.0.0.0
aqua-mongo     | 2019-09-06T07:47:15.895+0000 I  NETWORK  [initandlisten] waiting for connections on port 27017

Solution

That problem occur because you're trying to access from your Ubuntu, outside of Docker Network. And your Node container is inside that network so the way they communicate need to modify a bit to make it work. So I will refer my best practice way:

version: '2.1'

services:
  aqua-server:
    image: aqua-server
    build: .
    command: pm2-runtime process.yml
    container_name: "aqua-server"
    working_dir: /app
    environment:
      NODE_ENV: production
      AQUA_MONGO_IP: mongodb
      AQUA_MONGO_PORT: 27017
      AQUA_MONGO_DATABASE: aqua-server
      AQUA_EXPRESS_PORT: 3000
      AQUA_REDIS_PORT: 6379
      AQUA_REDIS_HOST: redis
    volumes:
      - .:/app/
    ports:
      - 3001:3000
    links:
      - mongodb
      - redis
    depends_on:
      - mongodb
      - redis
    networks: 
      frontend:
        ipv4_address: 172.20.0.2
  mongodb:
    image: mongo:4.2.0-bionic
    container_name: "aqua-mongo"
    environment:
      MONGO_LOG_DIR: /dev/null
    volumes:
      - /home/sagara/DockerVolume/MongoLocal:/data/db
    ports:
      - 3002:27017
    networks: 
      frontend:
        ipv4_address: 172.20.0.3
  redis:
    image: redis:5.0.5-alpine
    container_name: "aqua-redis"
    ports:
      - 3003:6379
    networks: 
      frontend:
        ipv4_address: 172.20.0.4
networks: 
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24

This way works because Docker handle the DNS for you and the domain names are the service name so that you can see in the docker-compose.yml above, I've changed AQUA_MONGO_IP to mongodb and AQUA_REDIS_HOST to redis. And I've changed the PORT too, Docker containers created by that docker-compose.yml will stay inside a network and they communicate by the PORT they exposed on their Dockerfile. So in this case other services can communicate with aqua-server via PORT=3000, aqua-server can communicate with mongodb service via PORT=27017 (this port is exposed inside Dockerfile of mongodb, EXPOSE 27017)

Hope that helps!



Answered By - Toan Quoc Ho