我有带有 docker(20.10.12)的 Linux Mint 主机。
该主机上有两个容器,使用简单创建docker run
,没有提供网络配置:
- mysql,已发布端口 3306,
- grafana,发布端口为3000。
两个容器都可以从外部访问(包括从同一网络中的另一台主机)。但我无法从 grafana 的容器连接到 msql。
对于连接,我使用主机的网络 IP(192.168.1.151)。
nc -zv 192.168.1.151 3306
从 grafana 容器内部“挂断”并且不提供任何输出。奇怪的是nc -zv 192.168.1.151 3000
也“挂断”。
检查后busybox
,结果相同——nc
也是“挂断”。
检查了一般网络问题:从容器内部成功连接到路由器和 google.com 的网络界面。
还检查了从容器内部我是否成功连接到主机本身的开放端口。
我知道我可以将两个容器链接到同一个docker网络,并完全跳过发布端口。但我更感兴趣的是解释为什么会发生这种情况。
答案1
当您启动没有自定义桥接网络设置的 Docker 容器时,Docker 会在默认桥接网络中启动它们。默认桥接网络具有不同的 IP 子网,无法通过主机 IP 地址进行路由。Docker 还会在默认桥接网络上通过容器名称禁用 DNS 解析。这在他们的文档
默认桥接网络上的容器只能通过 IP 地址相互访问,除非您使用 --link 选项(该选项被视为旧选项)。在用户定义的桥接网络上,容器可以通过名称或别名相互解析。
用户定义的桥接器提供容器之间的自动 DNS 解析。
端口发布只是使得主机上的应用程序能够连接容器。
这里的“IP地址”指的是容器的IP地址之内Docker 默认桥接网络,而不是主机 IP 地址。ip a
如果软件包安装在容器中,您可以通过命令从容器内获取 IP 地址,或者通过检查容器从 Docker 主机获取 IP 地址
docker inspect grafana | jq '.[].NetworkSettings.IPAddress'
"172.17.0.2"
docker inspect mysql | jq '.[].NetworkSettings.IPAddress'
"172.17.0.3"
使用这些 IP,您可以连接/验证连接性:
docker exec -it grafana sh
/usr/share/grafana $ nc -vz 172.17.0.3 3306
172.17.0.3 (172.17.0.3:3306) open
如果需要连接容器,可以创建自定义网络并加入容器。
docker network create monitoring
docker network connect monitoring mysql
docker network connect monitoring grafana
现在,当您检查网络时,您将看到两个容器都在网络上。
docker network inspect monitoring | jq '.[].Containers'
{
"9b1cd51b1350769b0842ce901c732482024e6f3f51e0c1b30ece8d6f19793079": {
"Name": "grafana",
"EndpointID": "8f881091c298bc18d92a463bcca10dce7f0813c7a5d9232b4c693644443644ac",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"d7b7d4bc66f617f824509e013b7e5bfb283652d85eb041ca04ced3ae8f8fe44c": {
"Name": "mysql",
"EndpointID": "99b514fa927601d98a2da10f820329add905a6d47a02e81322607a445617a320",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
}
您可以通过其容器名称连接到它们。
docker exec -it grafana sh
/usr/share/grafana $ nc -vz mysql 3306
mysql (172.18.0.2:3306) open