使用 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_healthy
下depends 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