3-2.Docker网络(二):容器的网络模式

前言

docker容器有四种网络模式可供选择,在有些书中,也会把这四种容器的网络模式称之为网络容器原型(例如在《docker in action》中),所有的docker容器都要属于这四种容器网络模式中的一种。

不同的容器网络模式对应着不同程度的隔离,按隔离程度由高到低的顺序排列是:none模式、bridged模式、container模式、host模式。其中,bridged模式是docker默认的网络模式,用户启动一个容器时,如果不特别规定使用哪一种网络模式,那么该容器使用bridged模式。

下图是《docker in action》中,描绘四种网络容器模式的原理以及与docker主机拓扑关系的图:
在这里插入图片描述

1.none模式

该模式下的容器,不允许任何的网络流量。启动该模式下的容器的方式是在docker run命令后加上–net none选项。执行命令docker container run -dit --name testnone --net=none alpine启动一个名为testnone的容器,采用none网络模式。容器启动完成之后,使用docker exec -it testnone sh命令进入容器中执行ifconfig结果如下图所示:
在这里插入图片描述
none模式下容器中的进程,只可以与自身通信或者与本地进程通信(也就是容器中的其他进程)。容器外的进程无法与容器内的进程通信,容器内的进程也无法与容器外的进程通信。另外还需注意,none模式下的容器可以被扩展它的网络功能以适应不同的情景。

2.bridge模式

bridge模式,是docker默认的容器启动模式,该模式下的容器有两个接口,一个是本地回环接口(127.0.0.1、localhost),另一个接口连接到docker引擎创建的桥接网络上(注意与Linux网桥docker0的区别,稍后会讲),执行命令docker container run -dit --name testbridge --net=bridge alpine创建一个bridge模式的容器testbridge(其中‘–net=bridge’可省略),然后执行docker exec -it testbridge sh进入容器中,ifconfig结果如下:
在这里插入图片描述

bridge模式下的网桥

docker daemon启动时会建立一个docker0网桥,这是一个Linux虚拟网桥。连接在该网桥上的所有容器属于同一个虚拟子网,它们之间能够相互通信,且可以通过docker0与外部的网络进行通信。该网桥一端连接到主机网络接口上,另一端和容器相连。
此外,还有一个桥接网络的概念,容器可以分属于不同的桥接网络,桥接网络由docker引擎管理,会被映射到Linux的网桥上。例如,默认的bridge网络被映射到docker0网桥上,可以通过命令docker network ls 查看主机上的桥接网络。

在这里插入图片描述

其中,(NAME列)bridge网络、host网络、none网络是默认创建的,localnet网络是我用docker network create -d bridge localnet创建的。
执行docker network inspect bridge命令可以查看bridge网络的相信信息,可以看到有哪些容器连接到了该网络上。如下图所示:
在这里插入图片描述
可以看到有一个名为testbridge的容器连接到了该网络中。同理,可以使用docker network inspect none查看none网络的详细信息,使用docker network inspect host查看host网络的详细信息。默认情况下,bridge模式的容器自动连接到bridge网络中,host模式的容器自动连接到host网络中,none模式的容器自动连接到none网络中,container模式的容器与其他容器共享网络接口,所以不需要再单独创建一个container网络。
在使用docker run命令运行容器时,可以通过–network参数,指定容器连接到哪个网络中。例如,执行docker run -dit --name testlocalnet --network localnet alpine启动一个bridge模式的容器testlocalnet,该容器不能与testbridge通信,因为属于两个不同的桥接网络。
下面进行一个实验,执行docker run -dit --name testlocalnet2 --network localnet alpine再启动一个bridge模式的容器testlocalnet2,与容器testlocalnet属于同一个桥接网络localnet。执行docker exec -it testlocalnet2 sh进入容器testlocalnet2中执行ping testlocalnet的结果如下所示:
在这里插入图片描述

注意:该实验如果要在bridge网络中进行的话,ping命令后面不能用容器的名字做参数,而要用容器的IP地址做参数,因为Linux系统中默认的bridge网络不支持通过docker DNS服务进行域名解析的,而自定义的桥接网络可以。
接下来从原理上解释一下为什么不属于同一个桥接网络的容器不能互相通信
在使用docker network create -d bridge localnet命令创建localnet网络时,内核也建立了一个新的虚拟网桥,也就是说在docker0网桥之外,建立了另一个网桥,localnet网络就映射到该网桥(br-9d5636f71221)上。可以通过brctl show命令查看。
在这里插入图片描述
每一个网桥都有自己的虚拟子网,不同的网桥的虚拟子网不同。在我的主机上,bridge网络的子网是172.17.0.0/16,localnet网络的子网是172.18.0.0/16,所以在容器testbridge里ping容器testlocalnet是ping不通的。
下面这张图参考《Docker Deep Dive》解释了Linux网桥,docker桥接网络,和docker容器的关系。
在这里插入图片描述

3.container模式

container模式下的容器,与另外一个运行中的容器共享同一个Network Namespace(网络命名空间,也可以说是网络栈),即两个容器在网络层面没有任何的隔离,它们的网络接口是相同的。第一个实验,执行docker container run -dit --name testcontainer --net=container:testnone alpine启动一个container模式下的容器,与第一节中的none模式的容器进行共享网络栈。注意,如果testnone容器不处于运行状态,则无法完成共享网络栈操作,testcontainer容器被创建,但是不会被运行。接着执行docker exec -it testcontainer sh命令,进入testcontainer容器中执行ifconfig结果如下所示:
在这里插入图片描述
第二个实验,我们启动一个新的容器,让它与第二节中的bridge模式的容器共享网络栈。执行命令:docker container run -dit --name testcontainer2 --net=container:testbridge alpine,接着执行命令docker exec -it testcontainer2 sh进入testcontainer2容器中执行ifconfig结果如下所示:
在这里插入图片描述
可以看到,testcontainer2容器eth0接口的IP地址也是172.17.0.2,与testbridge的一致。此外,还可以使用cat /etc/hosts命令,会看到两个容器的hosts文件中172.17.0.2地址对应的是同一个hostname。
container模式下的两个容器,拥有各自的文件系统和内存,共享的仅仅是网络组件。该模式的一个应用场景是扩展none模式下容器的网络功能,即我们的第一个实验的内容,位于两个none模式下的容器中的进程可以相互通信了。

4.host模式

在大多数的资料中都会提醒用户,该模式下的容器安全性极差,告诫用户谨慎使用该模式。host模式下的容器,在网络层面没有任何的隔离,对主机的网络有完全的访问权,共享主机的网络接口。执行docker run -dit --name testhost --net=host alpine启动一个host模式下的容器,然后执行docker exec -it testhost sh命令进入容器中,接着执行ifconfig命令,结果如下:
在这里插入图片描述
可以看到主机上所有的网络接口,包括docker0。

5.docker run中与网络相关的一些参数

--hostname +参数 用来指定容器的名字,仅用于DNS解析,设置该参数后会在容器内的/etc/hostname文件中看到结果。注意与–name选项的区别,–name选项可用于DNS解析,也可用于其他情景,比如docker stop 的参数等。
--dns +参数用来设置主DNS服务器,设置该参数后会在容器内的/etc/resolv.conf文件中看到结果。
--dns-search +参数用来指定进行DNS解析时的后缀,也叫DNS查找域。该参数被设定之后,DNS查询时,不包括顶级域名的主机名都会自动加上该后缀。例如--dns-search docker.com,那么nslookup registry.hub命令会解析registry.hub.docker.com的IP地址。
--add-host +参数用来自定义从主机名到IP地址的映射关系,例如,--add-host test:172.19.0.2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值