docker网络是如何工作的?

docker网络是如何工作的?,docker,Docker,docker网络机制中的IP分配过程有一些我不了解的地方。 假设我运行几个容器。每个都有自己的IP地址-这些IP地址来自何处? 如果其中一个容器侦听某个端口,我转到浏览器编写:并查看网页-我的计算机如何知道如何解决该问题(这是一个本地IP地址) 关于Docker网络的全面讨论超出了本文的范围,因此我将从您的问题中假设您所谈论的是bridge网络(这是默认设置) 启动Docker守护进程(Docker)时,它会在本地计算机上创建一个名为docker0的以太网桥网络接口 ~ > ifconf

docker网络机制中的IP分配过程有一些我不了解的地方。
假设我运行几个容器。每个都有自己的IP地址-这些IP地址来自何处?

如果其中一个容器侦听某个端口,我转到浏览器编写
并查看网页-我的计算机如何知道如何解决该问题(这是一个本地IP地址)

关于Docker网络的全面讨论超出了本文的范围,因此我将从您的问题中假设您所谈论的是
bridge
网络(这是默认设置)

启动Docker守护进程(
Docker
)时,它会在本地计算机上创建一个名为
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中表示为一个称为
网桥
的网络:

~ > 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
)的所有流量,使用TCP协议(
-p TCP
),目的地为端口7000(
--dport 7000
),实际将其路由到172.17.0.2:5000(
--目的地172.17.0.2:5000)。”。这当然有点简化了,但本质上是怎么回事

现在,如果启动另一个容器(这次让我们绑定到主机端口9999):

并快速检查其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(
——发送到目的地172.17.0.3:5000

停止容器,你会发现这些规则消失了


IANA是一位网络专家,所以有些东西可能会稍微简化,但希望能有所帮助

容器不会获得唯一的IP地址,而是获得唯一的端口(基于
dockerfile
中的
EXPOSE
)。您是否在询问您的计算机如何知道如何解析不同端口上的不同本地应用程序?它们确实具有唯一的IP地址。运行
docker inspect
可以显示
Networks.IPAddress
下的。也许我漏掉了什么东西,它会变得更糟。我不知道你的电脑是怎么解决的。我认为这与我在运行
ifconfig
时看到的一大堆问题有关。谢谢你的链接,我会检查的!请记住,docker网络有一系列模式(例如,
主机
覆盖
网桥
),它们的工作方式可能有所不同。阅读这些模式可能会回答您的许多问题:非常感谢您的详细解释!很好的解释很好的解释
~ > 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