【问题标题】:How does docker network work?码头工人网络如何工作?
【发布时间】:2018-05-10 23:17:03
【问题描述】:

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

【问题讨论】:

  • 容器没有获得唯一的 IP 地址,它获得了唯一的端口(基于dockerfile 中的EXPOSE)。您是在问您的机器如何知道如何解析不同端口上的不同本地应用程序?
  • 它们确实有唯一的 IP 地址。运行docker inspect <ID> 可以在Networks.IPAddress 下显示。也许我错过了什么..
  • 它得到一个private IP。不知道你的电脑是怎么解决的。我认为这与virtual network interfaces 有关,因为我在运行ifconfig 时看到了一大堆。
  • 好的。感谢您的链接,我会检查的!
  • 请记住,docker 网络有很多模式(例如hostoverlaybridge),它们的工作方式可能都略有不同。阅读这些模式可能会回答你的很多问题:docs.docker.com/network/#network-drivers

标签: docker


【解决方案1】:

关于 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 网络专家,所以有些东西可能会稍微简化,但希望对您有所帮助!

【讨论】:

  • 非常感谢您的详细解释!
  • 很好的解释
  • 很好的解释
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
  • 1970-01-01
  • 1970-01-01
  • 2017-02-01
  • 2018-06-19
  • 2021-10-01
相关资源
最近更新 更多