关于docker网络机制中IP分配的过程,我有些不了解。
假设我运行了几个容器。每个人都有自己的IP地址-这些IP地址来自哪里?
如果其中一个容器侦听端口,然后我进入浏览器并编写<IP>:<PORT>并查看网页-我的计算机如何知道解决该问题的方法(这是本地IP地址)?
这里不对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)
Run Code Online (Sandbox Code Playgroud)
如有必要,可以自定义,但通常使用默认值即可。
在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": {}
}
]
Run Code Online (Sandbox Code Playgroud)
注意,inet addr/ Gateway相同。另请注意:
"com.docker.network.bridge.name": "docker0"
Run Code Online (Sandbox Code Playgroud)
为了回答您的问题的一部分,您的容器IP地址是从172.17.0.0/16Docker创建的该子网()中分配的。现在我们知道已经设置了一些网络内容,让我们运行一个容器,看看会发生什么。
~ > docker run -d -p 7000:5000 johnharris85/simple-hostname-reporter:2
eeba0f9d23bbd3c10ddf61120ce5d7d1ded6db1515fc37725b68eae12ab6c9b5
Run Code Online (Sandbox Code Playgroud)
我们可以看到这个容器在我的网桥网络上有一个IP地址:
~ > docker container inspect eeb --format "{{ .NetworkSettings.Networks.bridge.IPAddress }}"
172.17.0.2
Run Code Online (Sandbox Code Playgroud)
实际上,我可以使用该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
Run Code Online (Sandbox Code Playgroud)
就我们而言,最重要的一行是我在上面留下的那一行。它说:“对于并非来自docker0接口(! -i docker0)的所有流量,使用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
Run Code Online (Sandbox Code Playgroud)
并快速检查它的IP:
~ > docker container inspect ac4 --format "{{ .NetworkSettings.Networks.bridge.IPAddress }}"
172.17.0.3
Run Code Online (Sandbox Code Playgroud)
现在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
Run Code Online (Sandbox Code Playgroud)
请注意,我们现在有了另一个规则,同样的结构,这次是说到端口9999的所有流量,都发送到我们的新容器IP(--to-destination 172.17.0.3:5000)。
停止容器,您会发现这些规则消失了!
IANA网络专家,所以有些内容可能会简化一些,但希望对您有所帮助!
| 归档时间: |
|
| 查看次数: |
842 次 |
| 最近记录: |