使用 docker-compose 连接到 RabbitMQ 容器

Posted

技术标签:

【中文标题】使用 docker-compose 连接到 RabbitMQ 容器【英文标题】:Connecting to RabbitMQ container with docker-compose 【发布时间】:2019-04-01 13:19:07 【问题描述】:

我想在一个容器中运行 RabbitMQ,在另一个容器中运行工作进程。 worker 进程需要访问 RabbitMQ。

我希望通过docker-compose 管理这些。

到目前为止,这是我的docker-compose.yml 文件:

version: "3"

services:

  rabbitmq:
    image: rabbitmq
    command: rabbitmq-server
    expose:
      - "5672"
      - "15672"

  worker:
    build: ./worker
    depends_on:
      - rabbitmq
    # Allow access to docker daemon
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

所以我公开了 RabbitMQ 端口。工作进程使用以下 URL 访问 RabbitMQ:

amqp://guest:guest@rabbitmq:5672/

这是他们在官方教程中使用的,但 localhost 已被替换为 rabbitmq,因为容器应该是 discoverable with a hostname identical to the container name:

默认情况下,Compose 会为您的应用设置一个网络。服务的每个容器都加入默认网络,并且该网络上的其他容器都可以访问它们,并且它们可以通过与容器名称相同的主机名发现。

每当我运行此程序时,我都会收到连接被拒绝错误:

Recreating ci_rabbitmq_1 ... done                                                                                                                                                    
Recreating ci_worker_1   ... done                                                                                                                                                    
Attaching to ci_rabbitmq_1, ci_worker_1                                                                                                                                              
worker_1    | dial tcp 127.0.0.1:5672: connect: connection refused                                                                                                                   
ci_worker_1 exited with code 1        

我觉得这很有趣,因为它使用 IP 127.0.0.1(我认为)是 localhost,尽管我指定了 rabbitmq 作为主机名。我不是 docker 网络方面的专家,所以也许这是需要的。

如果需要,我很乐意提供更多信息!


编辑

有一个几乎相同的问题here。我想我需要等到rabbitmq 启动并运行,然后再开始worker。我尝试通过健康检查来做到这一点:

version: "2.1"

services:

  rabbitmq:
    image: rabbitmq
    command: rabbitmq-server
    expose:
      - "5672"
      - "15672"
    healthcheck:
      test: [ "CMD", "nc", "-z", "localhost", "5672" ]
      interval: 10s
      timeout: 10s
      retries: 5

  worker:
    build: .
    depends_on:
      rabbitmq:
        condition: service_healthy

(注意不同的版本)。但是,这不起作用 - 它总是会因为不健康而失败。

【问题讨论】:

为什么需要暴露主机上的端口? 【参考方案1】:

啊哈!我修好了它。 @Ijaz 完全正确 - RabbitMQ 服务需要一段时间才能启动,我的工作人员会在它运行之前尝试连接。

我尝试使用延迟,但是当 RabbitMQ 花费的时间比平时更长时,这失败了。

这也表明了一个更大的架构问题——如果队列服务(在我的例子中是 RabbitMQ)在生产期间离线会发生什么?现在,我的整个网站都失败了。需要有一些内置的冗余和轮询。

正如this related answer 所述,我们可以在 docker-compose 3+ 中使用健康检查:

version: "3"

services:

  rabbitmq:
    image: rabbitmq
    command: rabbitmq-server
    expose:
      - 5672
      - 15672
    healthcheck:
      test: [ "CMD", "nc", "-z", "localhost", "5672" ]
      interval: 5s
      timeout: 15s
      retries: 1

  worker:
    image: worker
    restart: on-failure
    depends_on:
      - rabbitmq

现在,worker 容器将重新启动几次,而 rabbitmq 容器仍处于不健康状态。当nc -z localhost 5672 成功时,rabbitmq 立即变得健康 - 即当排队时!

【讨论】:

【参考方案2】:

这是正确的工作示例:

    version: "3.8"

    services:

    rabbitmq:
        image: rabbitmq:3.7.28-management
        #container_name: rabbitmq
        volumes:
            - ./etc/rabbitmq/conf:/etc/rabbitmq/
            - ./etc/rabbitmq/data/:/var/lib/rabbitmq/
            - ./etc/rabbitmq/logs/:/var/log/rabbitmq/
        environment:
            RABBITMQ_ERLANG_COOKIE: $RABBITMQ_ERLANG_COOKIE:-secret_cookie
            RABBITMQ_DEFAULT_USER: $RABBITMQ_DEFAULT_USER:-admin
            RABBITMQ_DEFAULT_PASS: $RABBITMQ_DEFAULT_PASS:-admin
        ports:
            - 5672:5672    #amqp
            - 15672:15672  #http
            - 15692:15692  #prometheus
        healthcheck:
        test: [ "CMD", "rabbitmqctl", "status"]
        interval: 5s
        timeout: 20s
        retries: 5

    mysql:
        image: mysql
        restart: always
        volumes:
        - ./etc/mysql/data:/var/lib/mysql
        - ./etc/mysql/scripts:/docker-entrypoint-initdb.d
        environment:
        MYSQL_ROOT_PASSWORD: root
        MYSQL_DATABASE: mysqldb
        MYSQL_USER: $MYSQL_DEFAULT_USER:-testuser
        MYSQL_PASSWORD: $MYSQL_DEFAULT_PASSWORD:-testuser
        ports:
        - "3306:3306"
        healthcheck:
        test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
        timeout: 20s
        retries: 10

    trigger-batch-process-job:
        build: .
        environment:
        - RMQ_USER=$RABBITMQ_DEFAULT_USER:-admin
        - RMQ_PASS=$RABBITMQ_DEFAULT_PASS:-admin
        - RMQ_HOST=$RABBITMQ_DEFAULT_HOST:-rabbitmq
        - RMQ_PORT=$RABBITMQ_DEFAULT_PORT:-5672
        - DB_USER=$MYSQL_DEFAULT_USER:-testuser
        - DB_PASS=$MYSQL_DEFAULT_PASSWORD:-testuser
        - DB_SERVER=mysql
        - DB_NAME=mysqldb
        - DB_PORT=3306
        depends_on:
        mysql:
            condition: service_healthy
        rabbitmq:
            condition: service_healthy

【讨论】:

不,这是错误的。 Compose 3+ 不支持condition: service_healthydepends on 测试一下:github.com/mnadeem/lob-proj-job-trigger-batch-process/blob/main/… 运行docker-compose up -d 后,您的示例没有在我的机器上运行,但我设法弄清楚为什么condition: service_healthy 首先对我不起作用,这要感谢您。所以你是对的。谢谢! 这其实是正确答案【参考方案3】:

如果您只是从另一个容器访问服务,也许您不需要公开/映射主机上的端口。

来自文档:

公开公开端口而不将它们发布到主机 - 它们只能被链接的服务访问。只有内部端口 可以指定。

expose:
 - "3000"
 - "8000"

所以应该是这样的:

version: "3"

services:

  rabbitmq:
    image: rabbitmq
    command: rabbitmq-server
    expose:
      - "5672"
      - "15672"

  worker:
    build: ./worker
    depends_on:
      - rabbitmq
    # Allow access to docker daemon
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

还要确保仅当它准备好在端口上服务器时才连接到 rabitmq。

【讨论】:

你绝对是对的——我不需要暴露主机上的端口,而只需要暴露给其他容器。不幸的是,这并不能解决连接问题,但我仍然学到了一些新东西:) @haz 连接问题可能与以下事实有关可以从那里连接【参考方案4】:

docker compose v3.8 最干净的方式

version: "3.8"

services:

  worker:
    build: ./worker
    rabbitmq:
        condition: service_healthy

  rabbitmq:
    image: library/rabbitmq
    ports:
    - 5671:5671
    - 5672:5672
    healthcheck:
      test: [ "CMD", "nc", "-z", "localhost", "5672" ]
      interval: 5s
      timeout: 10s
      retries: 3

【讨论】:

您不需要将“rabbitmq”行嵌套在另一个字段下吗?我收到此解决方案的错误提示未定义关键字 @HarrisonCramer 你是对的。缺少“服务”关键字。谢谢,答案已修改

以上是关于使用 docker-compose 连接到 RabbitMQ 容器的主要内容,如果未能解决你的问题,请参考以下文章

Springboot 容器使用 docker-compose 连接到 mongo 容器的 503 错误代码

如何从 docker-compose 连接到 Host PostgreSQL?

无法在 Docker-Compose 中使用 Spring Boot 连接到 MongoDB

无法从 docker-compose 文件中定义的另一个服务连接到 nsqd

Springboot 应用程序无法使用 docker-compose 连接到 MongoDB 容器

带有 docker-compose 的解析仪表板:无法连接到服务器