Docker 容器间相互访问 refused

2017-11-06 21:47:44 +08:00
 kismetX

我用 docker-compose.yml 配置了 nginx、web1、web2

nginx: build: ./nginx ports: - "80:80" expose: - "80" links: - "web1" - "web2"

auth: build: ./php expose: - "9000"

plan: build: ./php expose: - "9000"

nginx 里配了给 web1、web2 分别配了,web1.domain.comweb2.domain.com ,结果 web1 和 web2 不能相互访问,提示 connect refused,在宿主机可以访问 web1、web2,敢问各位大佬是什么原因。。在 web1 和 web2 容器里 ping 域名都是 127.0.0.1,应该是我在宿主机配置了 hosts 的原因

7645 次点击
所在节点    Docker
13 条回复
kkxxxxxxx
2017-11-06 22:11:04 +08:00
同一台宿主机的话,要么加入同一网桥,要么防火墙写对应的路由,目前只知道这两个
tomczhen
2017-11-06 22:35:50 +08:00
宿主机配置 host ?也就是用 host 改了域名的解析么?
那么不用 127.0.0.1 而是改成内网 IP 试试。
kismetX
2017-11-06 23:06:54 +08:00
@kkxxxxxxx 容器相互间本来就是处于同一局域网,应该不用这么加吧,你说的防火墙加路由不是很明白,防火墙不是用来过滤用的吗?
@tomczhen 容器的 ip 是动态的,给 nginx 的容器做了和宿主机的端口映射,原文里的是 docker-compose.yml 里的配置,展示和编辑时不一样~
tomczhen
2017-11-06 23:37:40 +08:00
哦,那建议去看官方文档关于 Network 和 DNS 这块的内容吧,希望能找到解决方法,洗洗睡。
kismetX
2017-11-06 23:53:06 +08:00
@tomczhen 看了一下。。英文很一般,单词都认识,就是看不懂~~
wwqgtxx
2017-11-07 07:36:29 +08:00
docker 默认的网络配置方式是一个私有网络加 nat 桥接,所以你在容器内访问 127.0.0.1 是访问的容器本身而不是宿主机
kismetX
2017-11-07 09:15:59 +08:00
@wwqgtxx 对,我是在宿主机访问容器 1,然后容器 1 访问容器 2,结果是 refused,我在容器 1ping 容器 2 的域名,显示的 ip 是 127.0.0.1,讲道理应该是在宿主机或 nginx 容器才会这样
wwqgtxx
2017-11-07 09:36:54 +08:00
@kismetX 你在容器内访问另一个容器应该用另一个容器的 name 而不是域名,你域名是在宿主机的 hosts 中配置的,在容器中会直接被继承,所以还是 127.0.0.1,而如果你访问容器名,docker 会在内部给你添加 dns 映射保证你访问 web01 的时候获得的就是 web01 这个容器的内网 ip
kismetX
2017-11-07 10:06:37 +08:00
@wwqgtxx 对,我刚刚也发现这个问题,于是我把宿主机的 hosts 改成了 docker 分配给宿主机的 ip,然后就可以了~
kismetX
2017-11-07 10:11:31 +08:00
@wwqgtxx
@tomczhen
@kkxxxxxxx
谢谢各位的帮忙啦^_^
tomczhen
2017-11-07 11:18:33 +08:00
@kismetX 说到底你还是没知道原因,其实如果是在网关上做 DNS 劫持解析域名的话你这个问题就不会遇到了。
tomczhen
2017-11-07 11:42:47 +08:00
总结一下吧。

默认的网络结构下,你可以把宿主机看成一个路由器,宿主机的内网 IP 就是路由器的 WAN IP,容器 LAN IP 就是路由器的 LAN 口,所有容器都是接在路由器的 LAN 口上,使用 P 参数暴露端口时就像在路由器上做端口映射。

你的情况是在宿主机上做 DNS 劫持,让两个域名解析为 127.0.0.1,这样宿主机访问域名实际是走的做了映射的 nginx 容器端口,但是其他两个容器是解析之后是访问自己。

解决方法:

1. 其他两个容器用 nginx 而不是域名访问 web

2. 把 HOST 的解析由 127.0.0.1 换成宿主机容器 LAN IP 或 LAN IP

切换到公网情况,这时为了保证所有客户端都正常,DNS 肯定是只能设置成宿主机的公网 IP,那么你不会遇到这个问题。在内网模拟的话,就是通过网关来劫持 DNS 记录,为了保证内网所有机器都能范围,那么劫持的记录肯定不是 127.0.0.1 而是你的宿主机内网 IP。
kismetX
2017-11-07 13:41:29 +08:00
@tomczhen 是的,起初在宿主机配置成 127.0.0.1 web1.domain.com 是因为给 nginx 和宿主机做了 80 端口映射,所以在宿主机访问 web1 其实就是访问 nginx,但是通过 docker 去配置容器后,因为容器解析域名时使用了宿主机的 hosts (这一步不知道 docker 是怎么操作的),所以容器内解析域名是 127.0.0.1,而非 nginx 容器是没有开 80 端口的,所以域名能 ping 通且为 127.0.0.1,80 端口自然无法访问

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/404097

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX