泊坞窗网络如何工作?

dfe*_*fek 3 docker

关于docker网络机制中IP分配的过程,我有些不了解。
假设我运行了几个容器。每个人都有自己的IP地址-这些IP地址来自哪里?
如果其中一个容器侦听端口,然后我进入浏览器并编写<IP>:<PORT>并查看网页-我的计算机如何知道解决该问题的方法(这是本地IP地址)?

joh*_*s85 9

这里不对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网络专家,所以有些内容可能会简化一些,但希望对您有所帮助!