简体   繁体   English

econnrefused rabbitMQ docker 容器之间

[英]econnrefused rabbitMQ between docker containers

I am trying to set up a simple docker-compose file which includes a rabbitmq container and a simple express server which connects to rabbitmq.我正在尝试设置一个简单的 docker-compose 文件,其中包括一个 rabbitmq 容器和一个连接到 rabbitmq 的简单快速服务器。 I'm getting the following error when trying to connect to rabbitmq from my express application:尝试从我的快速应用程序连接到 rabbitmq 时出现以下错误:

Error: connect ECONNREFUSED 172.19.0.2:5672
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1247:16) {
  errno: -111,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '172.19.0.2',
  port: 5672
}

I checked the IP-adress of the docker network manually to verify that 172.19.0.2 is indeed the rabbitmq process, which it is.我手动检查了 docker 网络的 IP 地址,以验证 172.19.0.2 确实是 rabbitmq 进程,它就是。

Here is my docker-compose:这是我的 docker-compose:

version: '3'
services:
  rabbitmq:
    image: rabbitmq:3-management-alpine
    container_name: 'rabbitmq'
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=pass
    ports:
      - 5672:5672
      - 15672:15672
  producerexpress:
    build: ./service1
    container_name: producerexpress
    ports:
      - 3000:3000
    environment:
      - PORT=3000
    depends_on:
      - rabbitmq

and the express app and its docker file:以及 express 应用程序及其 docker 文件:

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const amqp = require('amqplib');

const amqpUrl = process.env.AMQP_URL || 'amqp://admin:pass@172.19.0.2:5672';

let channel;
let connection;

connect();

async function connect(){
  try{
    connection = await amqp.connect(amqpUrl);
    channel = await connection.createChannel();

    await channel.assertQueue('chatExchange', {durable: false});
  } catch (err) {
    console.log(err);
  }
}

function sendRabbitMessage(msg) {
  channel.sendToQueue('chatExchange', Buffer.from(msg));
}


app.get('/', (req, res) => {
  let msg = 'Triggered by get request';
  sendRabbitMessage(msg);
  res.send('Sent rabbitmq message!');
});


app.listen(port, () => {
    console.log(`Server started on port ${port}`);
} );
FROM node:16

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

ENV PORT=3000

ENV AMQP_URL=amqp://admin:pass@172.19.0.2:5672

EXPOSE 3000

CMD ["npm", "start"]

This is my first time using docker compose and all the fixes I found on here seem to suggest I did everything correctly.这是我第一次使用 docker compose,我在这里找到的所有修复似乎都表明我做的一切都是正确的。 What am I missing?我错过了什么?

TL;DR TL;博士
The depends_on guarantes the order in which the services will start up, but that doesn't guarante anything for the processes they inititate. depends_on保证了服务启动的顺序,但这并不能保证它们启动的进程的任何内容。

In these cases, you should expand the depends_on statement in order to take into account the health status of the process of interest在这些情况下,您应该扩展depends_on语句to take into account the health status


Firstly, you should avoid making the communication of cointainers depend on their IP address but instead rely on their service names, since you are using docker compose.首先,您应该避免使硬币容器的通信依赖于它们的 IP 地址,而是依赖于它们的服务名称,因为您使用的是 docker 组合。

Meaning, instead of amqp://admin:pass@172.19.0.2:5672意思是,而不是amqp://admin:pass@172.19.0.2:5672

You should use amqp://admin:pass@rabbitmq:5672你应该使用amqp://admin:pass@rabbitmq:5672


Moving on to the core issue, your producerexpress relies on to rabbitmq in order to function.继续核心问题,您的producerexpress依赖于rabbitmq以实现 function。

As a result, you added the depends_on statement to producerexpress to resolve this.因此,您将depends_on语句添加到producerexpress以解决此问题。 But this is not enough, quotting from https://docs.docker.com/compose/startup-order/但这还不够,引自https://docs.docker.com/compose/startup-order/

You can control the order of service startup and shutdown with the depends_on option.您可以使用depends_on选项控制服务启动和关闭的顺序。 Compose always starts and stops containers in dependency order, .... However, for startup Compose does not wait until a container is “ready” (whatever that means for your particular application) - only until it's running . Compose 总是按依赖顺序启动和停止容器,....但是, for startup Compose does not wait until a container is “ready” (whatever that means for your particular application) - only until it's running

As a result, you need to add a health check in order to guarantee that the rabbitmq process has started successfully, not just the container .因此,您需要添加health check以保证rabbitmq process has startednot just the container

In order to achieve that you should alter your compose file为了实现这一点,您应该更改您的compose文件

version: '3'
services:
  rabbitmq:
    build: ./rabbitmq
    container_name: 'rabbitmq'
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=pass
    ports:
      - 5672:5672
      - 15672:15672
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:15672"]
      interval: 30s
      timeout: 10s
      retries: 5

  producerexpress:
    build: ./service1
    restart: on-failure
    container_name: producerexpress
    ports:
      - 3000:3000
    environment:
      - PORT=3000
    depends_on:
      rabbitmq:
        condition: service_healthy

In order to make the healthcheck, we need the curl package in the rabbitmq image, so add the following Dockerfile为了进行健康检查,我们需要curl映像中的 curl package,因此添加以下 Z386CCCC94FB75ZFF29

FROM rabbitmq:3-management-alpine
RUN apk update
RUN apk add curl
EXPOSE 5672 15672

Finally, to make this change compatible create the following directory structure最后,为了使此更改兼容,请创建以下目录结构

./docker-compose.yml
./rabbitmq/
 --- Dockerfile
./service1/
 --- Dockerfile

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM