2团
Published on 2024-08-16 / 12 Visits
0
0

Dokcer网络模式

Docker网络模式主要有Bridge、Host以及None模式,在后续的版本中,还增加了Overlay模式。因为Overloay模式使用较少,本文不做具体探究。

1. 网络接口

截图 2023-09-13 20-27-12.png

上图为实验机器的网络接口,主要为lo以及wlp2s0,其中lo为环回接口,wlp2s0是wifi接口。

接口中的配置信息含义如下:

  • BROADCAST:该接口支持广播;

  • MULTICAST:该接口支持多播;

  • UP:网络接口已启用;

  • LOWER_UP:网络电缆已插入,设备已连接至网络;

还有些附加的信息:

  • mtu 1500:最大传输单位(数据包大小)为1500字节;

  • qdisc pfifo_fast:数据包排队;

  • state UP:网络接口已启用;

  • group default:接口组;

  • qlen 1000:传输队列长度;

  • link/ether:接口的MAC(硬件地址);

  • brd:广播地址;

  • scope global:全局有效;

  • dynamic :地址是动态分配的;

  • valid_lft:IPv4/Ipv6地址的有效使用期限;

  • preferred_lft:IPv4/Ipv6地址的首选生存期;

  • scope link:仅在此设备上有效;

安装docker后,会发现系统中将添加一个docker0接口,具体如下:

截图 2023-09-13 20-28-41.png

需要注意 ,docker0接口的IPv4地址是172.17.0.1/16,这是一个私有地址。

2. 网络模式

Docker默认的网络模式是Bridge、Host以及None,默认采用的是Bridge;docker0接口就是Docker创建的网桥。

截图 2023-09-13 20-30-57.png
查看Docker的Bridge网络模式信息,具体如上图,由图可知:

  • 当前Docker的网络模式为bridge;

  • 当前Docker的网络网关是172.17.0.1。

3. 默认网桥实践

截图 2023-09-13 20-33-22.png

创建容器,未具体设置网络模式,具体如上所示。

待容器创建好之后,查看Docker的Bridge网络模式信息,具体如下:

截图 2023-09-13 20-34-30.png

查询得到信息如上所示,可知默认网桥中的Containers属性中,添加了egg1容器的网络信息,且egg1的IPv4地址为172.17.0.2。

截图 2023-09-13 20-48-06.png

查看宿主机的网络接口,可发现当前接口中增加了索引号为5的接口veth9e04568@if4,

其中接口的前缀veth表示虚拟网络设备对,其出现的目的,是为了解决Linux中不同网络namespace之间的通信。veth接口成对出现,在veth接口的一端发送信息,另一端就会接收到信息,反之亦然。

查看veth9e04568接口的具体信息,具体如下图所示:

截图 2023-09-13 20-50-34.png

需要重点注意的是,veth9e04568的master是docker0,也就是说veth9e04568依赖于docker0接口进行通信。

注意到veth9e04568接口的索引是5,那么宿主机上为什么没有出现索引为4的接口呢;且veth是虚拟网络设备对,那么肯定存在对应的接口,这个隐藏的接口是不是接口4呢?进入创建的egg1容器,查询接口信息如下所示:

截图 2023-09-13 20-57-16.png

由上图可知,容器中的接口索引分别为1和4,其中1号接口为lo接口,对其进行忽略。查看容器内的4号接口信息,可知4号接口的类型(info_kind)为veth,且其链接(link_index)的接口索引是5(对应宿主机上索引为5的接口)。因此,宿主机上消失的4号接口隐藏在创建的容器内,4号接口与5号接口形成一对,借此完成容器与外界的通信。

为了验证此想法,我们接着创建egg2容器,并查看宿主机的接口信息,具体如下所示:

截图 2023-09-13 21-02-43.png截图 2023-09-13 21-03-22.png

通过上面两图可知,此前的推断无误。

image-eipc.png

veth与docker0,以及宿主机的关系,可大致参见上图。

4. 默认网桥通信

截图 2023-09-13 21-08-13.png

进入egg1容器,通过ping查看容器的网络可达性,由上图可知:

  • 容器可访问到docker0接口对应的网关地址;

  • 容器可访问到www.baidu.com,说明可访问外网;

  • 容器可通过具体的IP地址访问到挂载在docker0的容器egg2;

  • 容器无法通过主机名访问到挂载在docker0的容器egg2;

  • 宿主机上可通过具体的IP地址访问到容器egg1。

5. 宿主机访问容器

由上文可知,宿主机可通过容器的IP地址访问到容器,但是这样不太方便,且通过网桥进行网络通信也会降低网络效率,那么是否可以将容器的端口直接映射至宿主机进行访问呢?

答案是可以,只需要在启动容器时指定端口映射,可看下面示例:

截图 2023-09-14 21-05-56.png

示例中创建了nginx容器,并且将容器的80端口映射至宿主机的8080端口。待容器运行后,此时可直接访问宿主机的8080端口,发现正确显示nginx代理信息,表明通过端口映射,可轻松访问到容器内的应用,无需记住容器的具体IP地址信息。

6. 容器互相访问

上文中阐述,挂载在同一网桥的容器之间,只能通过容器的具体IP进行访问。这种方式,存在几个问题:

  • 容器的IP并不是固定的,在容器重启,或宿主机重启的情况下,容器的IP可能发生变化;

  • 容器的IP是在容器创建之后才确定的,无法进行提前规划;

  • 通过IP进行访问,还是不如域名或者主机名来的便捷;

因此,我们寻求一种能够通过主机名或者容器名访问其他容器的方式。这个也比较方便,只需要自行创建网桥,挂载在自定义网桥上的容器就可以通过主机名或者容器名互相访问。具体如下所示:

截图 2023-09-14 21-09-04.png

创建自定义网桥(bridge模式),命名为dnsnet。查看宿主机接口,发现多出一个接口,如下所示:

截图 2023-09-14 21-09-24.png

宿主机上多出索引为10的接口,命名以br开头,查看接口信息,如下所示:

截图 2023-09-14 21-11-18.png

由上图可知,dnsnet网桥的网关为172.18.0.1,区别于docker0的网关172.17.0.1,其他信息与docker0基本一致。

创建容器egg3,启动命令中,指定容器挂载于dnsnet网桥下。

截图 2023-09-14 21-14-35.png

查看egg3容器的veth信息,可发现egg3容器的veth接口的master为dnsnet接口。

截图 2023-09-14 21-16-53.png

此时继续创建egg4容器,指定网络挂载于dnsnet下,查看dnsnet信息可发现,内部包含egg3以及egg4容器。进入egg4容器,此时发现可直接ping通egg3,不需要填写egg3的IP地址。

7. Host模式

Host模式比较简单,即容器的网络直接使用宿主机的网络,无需进行bridge进行地址转换,也无需进行端口映射暴露端口供外界使用。但是这种模式亦存在局限,在宿主机内创建大量容器的情况下,容器内的端口可能存在端口冲突。

以下通过Host模式创建nginx容器(需要删除之前创建的nginx容器)。

截图 2023-09-14 21-19-32.png

上图中可发现,删除直接创建的nginx容器后,curl无法调用。此时直接创建基于Host模式的nginx容器,无需进行端口映射,宿主机即可直接访问nginx服务。

8 None模式

使用None模式创建的容器,无法访问外网,亦无法访问外网。

9. 出处

本文是观看【入门篇】Docker网络模式Linux - Bridge | Host | None视频,觉得视频质量很高,因此整理成文字版本,感谢UP主技术蛋老师。


Comment