Docker 容器在运行时,会涉及多个容器相互连接,甚至与宿主机上的应用连接的问题。既然需要产生连接,那么就必然要依赖网络。
网络在Docker的技术体系中,是一个不容易搞清楚的要点。因此,希望您读完本文之后,对 Docker 网络有一个通透的理解。
首先,我们花几分钟的时间,回顾网络是什么。
网络不仅仅是计算机术语,在我们的生活中,网络无处不在。
任何一个被称之为网络的事物都是由“终端节点+中心节点”组成。如果多个小的网络联合起来,就组成了大网络。
这里有一个概念值得注意,不管是是终端节点还是中心节点,它们都是节点。即它们的“物理属性”是一个层面,而逻辑上的分工又不是一个层面。
节点与节点连接起来,就组成网络。中心节点对(网络)内起着与其他终端节点沟通的作用,对(网络)外起着与外部连接的功能,甚至是连接外部的唯一通道。
其实,只要能够分辨清楚哪些是终端节点,哪些是中心节点,就完全从宏观上把握住了网络。剩下的,就是搞清楚它们之间的数据流向。
为了了解 Docker 网络,我们先在已经运行 Docker 的主机上运行一条命令
docker network ls
[root@iZ8vb7iZ ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 06008f57697f blogwebsoft9com_default bridge local f13768fd7a20 bridge bridge local 7d6412aa6e40 host host local e5e6049b8d9f none null local 29eae24dae84 portainer_default bridge local b286f40bc93d websoft9com_default bridge local
以上显示的就是 Docker 管辖的所有中心节点网卡(先不称之为网络)名称。而容器内部也有网卡,但不会在此命令中列出。
> 网卡也被称之为网络接口
Docker 的网络中,每一个运行中的容器就是网络中的终端节点,这个很好理解。
要正确理解这个问题,先熟悉一个 Docker 网络相关的设计:在安装 Docker 时,Docker 会自动创建三个(虚拟)中心节点网卡,同时宿主机上创建一个名称为 docker0 的(虚拟)中心网卡。
下面分别介绍 Docker 内部的三个网卡:
sudo docker run -it phpmyadmin
sudo docker run -it --net="host" phpmyadmin
如果您读到此处,仍然一知半解,我想可能需要向您澄清一个概念。
网络上绝大部分关于 Docker 网络相关的博客,都没有仔细斟酌网络这个词的用法,不该出现的“网络”的地方错用了这个词,很容易让读者无法理解本质。
所以我们再回顾一次:
ifconfig
命令查看,可知其格式基本一致docker0: flags=4099 mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:f6ff:fead:46 prefixlen 64 scopeid 0x20 ether 02:42:f6:ad:00:46 txqueuelen 0 (Ethernet) RX packets 2831 bytes 2150398 (2.0 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2406 bytes 682422 (666.4 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth0: flags=4163 mtu 1500 inet 172.26.72.241 netmask 255.255.240.0 broadcast 172.26.79.255 inet6 fe80::216:3eff:fe0a:e07c prefixlen 64 scopeid 0x20 ether 00:16:3e:0a:e0:7c txqueuelen 1000 (Ethernet) RX packets 1146393 bytes 760158453 (724.9 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 836693 bytes 355058824 (338.6 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
中心节点:网卡中有一种特殊网卡,我们称之为中心节点网卡或网桥,其他的网卡都与之相连,由它负责内部网卡之间的通信和外部的通信出口中转。
网络:多个网卡之间通过某种形式组合起来,可以按设计进行通信,就形成了网络。网络一般采用“中心节点+多个终端节点”的组网模式。
容器中端口与服务器的端口是一个概念。
端口即应用程序在网卡中占用的访问通道。例如:一个容器中安装了 Apache 和 MySQL 两个软件,而这个容器只有一个虚拟网卡,如何保证两个软件都可以被外界访问又互不干扰?
计算机的设计者会给网卡虚拟很多访问通道,并给与从0到65535的数字编号,这个编号就是端口。需要用到网络通道的软件可以配置不同的数字编号,比如:Apache 使用 80 端口,MySQL 使用 3306 端口。
拿一个真实世界的例子可能更有助于理解端口。
比如去一栋办公大楼(只有一个门牌地址),如何保证各种不同的人群安全有序的进出?
一般来说,管理非常规范的办公楼可能会有:员工通道(001号门)、访客通道(002号门)、消防通道(003号门)、物流通道(004号门)等各种不同的门,不同的人群通过不同的通道进出,其中每一个门就相当于一个端口。
理解了上面的 Docker 网络模式之后,在设置 Docker 容器被外网访问就变得非常简单。
常见的容器通信常见包括:
容器之间通信
容器与宿主机通信
容器直接与外部网络通信
用于在两个容器之间创建一个之间连接的虚拟通道(在 /etc/hosts 文件中增加被连接的容器名称和IP信息),而不必通过网桥连接。
可以,但是比较复杂。
会。一般以当前目录文件夹名称+default,例如:blogwebsoft9com_default 这个网卡的名称来源于在blog.websoft9.com目录下基于 docker-compose 创建容器
会
不会,默认使用已经存在的 bridge
docker network ls 查看到的网卡也会被显示到宿主机下