Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker and Rabbitmq: ECONNREFUSED between containers

I am trying to setup separate docker containers for rabbitmq and the consumer for the container, i.e., the process that would listen on the queue and perform the necessary tasks. I created the yml file, and the docker file.

I am able to run the yml file, however when I check the docker-compose logs I see where there are ECONNREFUSED errors.

NewUserNotification.js:

require('seneca')()
    .use('seneca-amqp-transport')
    .add('action:new_user_notification’, function(message, done) {
        … 

        return done(null, {
        pid: process.pid,
        status: `Process ${process.pid} status: OK`
    })
    .listen({
        type: 'amqp',
        pin: ['action:new_user_notification’],
        name: 'seneca.new_user_notification.queue',
        url: process.env.AMQP_RECEIVE_URL,
        timeout: 99999
    });

error message in docker-compose log:

    {"notice":"seneca: Action hook:listen,role:transport,type:amqp failed: connect ECONNREFUSED 127.0.0.1:5672.","code":
    "act_execute","err":{"cause":{"errno":"ECONNREFUSED","code":"ECONNREFUSED","syscall":"connect","address":"127.0.0.1",
    "port":5672},"isOperational":true,"errno":"ECONNREFUSED","code":"act_execute","syscall":"connect","address":"127.0.0.1",
    "port":5672,"eraro":true,"orig":{"cause":{"errno":"ECONNREFUSED","code":"ECONNREFUSED","syscall":"connect","address":"127.0.0.1",
    "port":5672},"isOperational":true,"errno":"ECONNREFUSED","code":"ECONNREFUSED","syscall":"connect","address":"127.0.0.1","port":5672},
    "seneca":true,"package":"seneca","msg":"seneca: Action hook:listen,role:transport,type:amqp failed: connect ECONNREFUSED 127.0.0.1:5672.",
    "details":{"message":"connect ECONNREFUSED 127.0.0.1:5672","pattern":"hook:listen,role:transport,type:amqp","instance":"Seneca/…………/…………/1/3.4.3/-“,
    ”orig$":{"cause":{"errno":"ECONNREFUSED","code":"ECONNREFUSED","syscall":"connect","address":"127.0.0.1","port":5672},"isOperational":true,
"errno":"ECONNREFUSED","code":"ECONNREFUSED","syscall":"connect","address":"127.0.0.1","port":5672}

sample docker-compose.yml file:

version: '2.1'
services:
 rabbitmq:
    container_name: "4340_rabbitmq"
    tty: true
    image: rabbitmq:management
    ports:
      - 15672:15672
      - 15671:15671
      - 5672:5672
    volumes:
      - /rabbitmq/lib:/var/lib/rabbitmq
      - /rabbitmq/log:/var/log/rabbitmq
      - /rabbitmq/conf:/etc/rabbitmq/
account:
    container_name: "account"
    build:
      context: .
      dockerfile: ./Account/Dockerfile
    ports:
      - 3000:3000
    links:
      - "mongo"
      - "rabbitmq"
    depends_on:
      - "mongo"
      - "rabbitmq"
new_user_notification:
    container_name: "app_new_user_notification"
    build:
      context: .
      dockerfile: ./Account/dev.newusernotification.Dockerfile
    links:
      - "mongo"
      - "rabbitmq"
    depends_on:
      - "mongo"
      - "rabbitmq"
    command: ["./wait-for-it.sh", "rabbitmq:5672", "-t", "90", "--", "node", “newusernotification.js"]

amqp connection string: (I tried both ways, with and without a user/pass) amqp://username:password@rabbitmq:5672

I added the link attribute to the docker-compose file and referenced the name in the .env file(rabbitmq). I tried to run the NewUserNotification.js file from outside the container and it started fine. What could be causing this problem? Connection string issue? Docker-Compose.yml configuration issue? Other?

like image 680
user1790300 Avatar asked Dec 28 '17 23:12

user1790300


2 Answers

Seems the environment variable AMQP_RECEIVE_URL is not constructed properly. According to error log the listener is trying to connect to localhost(127.0.0.1) which is not the rabbitmq service container IP. Find the modified configurations for a working sample.

1 docker-compose.yml

version: '2.1'
services:
 rabbitmq:
    container_name: "4340_rabbitmq"
    tty: true
    image: rabbitmq:management
    ports:
      - 15672:15672
      - 15671:15671
      - 5672:5672
    volumes:
      - ./rabbitmq/lib:/var/lib/rabbitmq
 new_user_notification:
    container_name: "app_new_user_notification"
    build:
      context: .
      dockerfile: Dockerfile
    env_file:
      - ./un.env
    links:
      - rabbitmq
    depends_on:
      - rabbitmq
    command: ["./wait-for-it.sh", "rabbitmq:5672", "-t", "120", "--", "node", "newusernotification.js"]

2 un.env

AMQP_RECEIVE_URL=amqp://guest:guest@rabbitmq:5672

Note that I've passed the AMQP_RECEIVE_URL as an environment variable to new_user_notification service using env_file and got rid of the account service

3 Dockerfile

FROM node:7
WORKDIR /app
COPY newusernotification.js /app
COPY wait-for-it.sh /app
RUN npm install --save seneca
RUN npm install --save seneca-amqp-transport

4 newusernotification.js use the same file in the question.

5 wait-for-it.sh

like image 121
Anuruddha Avatar answered Nov 14 '22 10:11

Anuruddha


It is possible that your RabbitMQ service is not fully up, at the time the connection is attempted from the consuming service.

If this is the case, in Docker Compose, you can wait for services to come up using a container called dadarek/wait-for-dependencies.

1). Add a new service waitforrabbit to your docker-compose.yml

waitforrabbit:
  image: dadarek/wait-for-dependencies
  depends_on:
    - rabbitmq 
  command: rabbitmq:5672

2). Include this service in the depends_on section of the service that requires RabbitMQ to be up.

depends_on: 
  - waitforrabbit

3). Startup compose

docker-compose run --rm waitforrabbit
docker-compose up -d account new_user_notification

Starting compose in this manner will essentially wait for RabbitMQ to be fully up before the connection from the consuming service is made.

like image 43
grizzthedj Avatar answered Nov 14 '22 10:11

grizzthedj