最近写一个使用了 RabbitMQ 的 spring boot 项目,采用 docker 部署,所以有一个 openjdk 容器和一个 rabbitmq 容器,docker-compose.yml 里面是这样定义的:
services:
core:
build:
context: .
dockerfile: docker/core/Dockerfile
ports:
- 8080:8080
rabbitmq:
build:
context: .
dockerfile: docker/rabbitmq/Dockerfile
ports:
- 5672:5672
- 15672:15672
然后项目的 application.yml 里面,把 localhost 替换成 rabbitmq
spring:
rabbitmq:
host: rabbitmq
port: 5672
这样后端到 rabbitmq 的连接是正常的,但是前端用 websocket 连 rabbitmq 的 stomp (插件已开)却总是报错( 61613 端口也试了):
var ws = new WebSocket('ws://rabbitmq:15674/ws');
var client = Stomp.over(ws);
报错信息:
WebSocket connection to 'ws://rabbitmq:15674/ws' failed: Error in connection establishment: net::ERR_NAME_NOT_RESOLVED
想问下 websocket 这里应该怎么写地址才能实现两个容器间的通信?
1
40huo 2019-07-14 00:46:28 +08:00 via Android
docker compose 里加上 link
|
2
gzlock 2019-07-14 01:40:56 +08:00
要 link 同名容器,host 就是容器名字
可以参考官方 docker-compose 的配置例子,有写的 |
3
also24 2019-07-14 01:50:22 +08:00
前端指的是前端网页上?
网页上的代码,跑在你的浏览器上,也就是跑在客户端的系统上。 客户端的系统上,怎么会有 rabbitmq 这个 host 呢?自然就连不上了。 配置文件里把 15672 端口转发出来了,也就是说目前这个服务监听了宿主机的 15672 端口。 因此,此处应当写你的 docker 宿主机的 IP 或 hostname:ws://docker_server_ip:15672/ws 另外:你配置里的端口号是 15672,代码里是 15674,记得改掉 |
4
1oNflow OP |
5
1oNflow OP @also24 rabbitmq 的容器的地址按理说就是 rabbitmq (替换了 localhost ),而且 java 代码访问 rabbitmq 就没问题。
15672 是网页管理器的端口,stomp 的端口是 15674,这个没暴露出来给容器外访问,难道是因为这个? |
6
carlclone 2019-07-14 11:11:24 +08:00 via Android
你把前端也部署在容器里就好了
|
7
salamanderMH 2019-07-14 11:15:23 +08:00
客户端的系统上,肯定没有 rabbitmq 这个 host,自然就连不上了。
|
8
also24 2019-07-14 12:07:20 +08:00 via Android
@1oNflow
你仔细想一下你的前端代码运行在什么地方。 另外,端口的问题,你需要从容器外部访问的端口,自然需要映射出来。 还有就是,我感觉你似乎需要了解下映射到 0.0.0.0 和映射到 127.0.0.1 的不同。 |
9
Hopetree 2019-07-14 13:11:24 +08:00 via iPhone
如果前端不是容器的话,那就使用 127 加本地映射端口啊
|
10
1oNflow OP @also24 前端忘了在正文里说了,就是 spring 加模板引擎,后端渲染的 html,所以前后端都在一个 jar 一个容器里。我看 java 后台连接 rabbitmq 没问题就以为前端也应该没问题。
后来开放了 mq 容器的 15674 端口,问题就解决了,原以为 compose 的两个容器会有更紧密的联系(相比于 docker 外的用户),可以直接互相访问… |
11
also24 2019-07-14 16:22:39 +08:00
@1oNflow #10
说实话我实在是没看懂你的 “前端” 到底指的是什么。 你所说的 “前端”,究竟指的是哪部分代码。 到底是谁在连接 rabbitmq 的 websocket ? 是说输出 ->前端页面<- 的 ->后端 Java 代码<- 去连接 websocket ? 还是在说 ->前端页面上的 JavaScript <- 本身去连接 websocket ? 我看了下 STOMP 是个 js 插件,所以我理解为你说的是第二种情况, 这种情况我不觉得单纯的开放端口就能解决。 你的错误代码也很明确的表示了:net::ERR_NAME_NOT_RESOLVED 是主机名没有被找到,而不是端口连接超时失败之类的。 我现在开始很好奇你到底是怎样的情况了。 |
12
hantsy 2019-07-14 22:49:45 +08:00
客户端 JS 程序,除非是部署在一个 Docker 环境,如 K8s,Docker Swarm, 否则用 IP 连接吧。
用 docker-compose 运行后,可以直接查到虚拟机 IP 地址,docker-machine env. 也可以用 Localhost,127.0.0.1,前提是虚拟机 IP 映射到本地 IP。 我用 Docker Toolbox 比较多,Virtualbox 可以用命令映射服务地址,例如,VBoxManage modifyvm "meandev" --natpf1 "tcp-port3306,tcp,,3306,,3306" |