关于 Docker 网络的完整讨论超出了此处的范围,因此我将根据您的问题假设您正在谈论 bridge 网络(这是默认设置)。
当您启动 Docker 守护程序 (dockerd) 时,它会在您的本地计算机上创建一个名为 docker0 的以太网桥网络接口。
~ > ifconfig
docker0 Link encap:Ethernet HWaddr 12:42:09:64:a9:dd
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:9ff:fe64:a9da/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:86 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:11923 (11.9 KB)
如果需要,可以自定义,但通常默认设置就可以了。
这在 Docker 中表示为一个名为 bridge 的网络:
~ > docker network inspect bridge
[
{
"Name": "bridge",
"Id": "25191b73563206a321498c0fac55a897de6ba0333d19f0bdc32c78d290b9fedc",
"Created": "2018-05-07T18:31:08.680222396-07:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
注意inet addr / Gateway 是相同的。另请注意:
"com.docker.network.bridge.name": "docker0"
为了回答您的部分问题,您的容器 IP 地址是从 Docker 创建的这个子网 (172.17.0.0/16) 分配的。现在我们知道一些网络的东西已经设置好了,让我们运行一个容器看看会发生什么。
~ > docker run -d -p 7000:5000 johnharris85/simple-hostname-reporter:2
eeba0f9d23bbd3c10ddf61120ce5d7d1ded6db1515fc37725b68eae12ab6c9b5
我们可以看到这个容器在我的桥接网络上有一个ip地址:
~ > docker container inspect eeb --format "{{ .NetworkSettings.Networks.bridge.IPAddress }}"
172.17.0.2
事实上,我可以使用该 IP 地址和 容器 端口来访问我的应用程序(在浏览器中尝试 172.17.0.2:5000!)。但是,这不是非常可扩展/动态的,因为当我的容器重新启动时,这个 IP 地址可能会改变。而且我必须做很多事情才能找到它。
我不必这样做,而是将主机上的端口 7000 映射到容器中的端口 5000(这是我的应用程序正在侦听的端口),这样我就可以在浏览器中访问 localhost:7000 并点击我的应用程序(也试试吧!)。
好的,那么是什么让我机器上 7000 端口的流量神奇地路由到我容器中的 5000 端口?
我们来看看iptables!:
~ > sudo iptables -t nat -S
# ... some stuff
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 7000 -j DNAT --to-destination 172.17.0.2:5000
就我们而言,(最)重要的一行是我在上面留下的那一行。它说“对于来自 docker0 接口 (! -i docker0) 的所有流量 not,使用 TCP 协议 (-p tcp),发往端口 7000 (--dport 7000),实际上将其路由到 172.17 .0.2:5000 (--to-destination 172.17.0.2:5000)”。当然,这有点简化,但基本上是发生了什么。
现在如果你启动另一个容器(这次让我们绑定到主机端口 9999):
~ > docker run -d -p 9999:5000 johnharris85/simple-hostname-reporter:2
ac4df2bd0a961bfa08735d64fa7f6e69f171e7e499fb86d2ecac6cfba350a5d4
然后快速检查一下它的 IP:
~ > docker container inspect ac4 --format "{{ .NetworkSettings.Networks.bridge.IPAddress }}"
172.17.0.3
现在再次iptables:
~ > sudo iptables -t nat -S
# ... some stuff
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 7000 -j DNAT --to-destination 172.17.0.2:5000
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 9999 -j DNAT --to-destination 172.17.0.3:5000
请注意,我们现在有另一条规则,相同的结构,这一次表示将所有到端口 9999 的流量发送到我们的新容器 IP (--to-destination 172.17.0.3:5000)。
停止容器,您会发现这些规则消失了!
IANA 网络专家,所以有些东西可能会稍微简化,但希望对您有所帮助!