docker的五种网络模式
容器通信模式分类
模式名称 | 简介 | 备注 |
---|---|---|
bridge | 容器拥有独属于自己的虚拟网卡和虚拟IP等网络资源,通过docker0虚拟网卡与宿主机的eth0网卡交互,进而与外界网络交互。 | 默认模式 |
host | 容器不拥有任何独立网络资源,与宿主机共享网络空间。 | 弊端:同一端口只能被一个容器服务绑定 |
none | 关闭容器网络功能,仅有独立网络空间但无任何网络资源分配(如虚拟网卡、路由、IP等)。 | 极少使用,适用于需隔离网络环境的场景 |
container | 首个容器以bridge模式启动,后续容器共享首个容器的网络资源,保持其他资源隔离。 | 若首容器停止,依赖其网络的容器也将失去网络连接 |
自定义 | 通过-d 指定网络模式类型,支持bridge或overlay(支持多subnet子网配置)。 | 支持容器间使用别名通信,提高了网络配置的灵活性和便利性 |
docker0虚拟网卡:
当docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,宿主机上以Bridge模式启动的容器会链接到这个虚拟网桥上。docker0默认地址172.17.0.0/16。虚拟网桥的工作方式和物理交换机类似,这样宿主机上的所有容器就通过docker0连在一个二层网络中,再通过docker0和物理网卡enp4s0交互。
docker安装启动后就会默认的创建三种网络,bridge,host,none,这三种也是docker的基础网络,后面两种将会在这三种上进行拓展。
先查看一下docker刚启动的时候宿主机上的网络是什么样子的
只有宿主机自身网卡和docker启动创建bridge网络时在宿主机创建的docker0虚拟网卡。
bridge桥接网络模式(默认模式)
特点:
1.默认为每个容器分配单独的网络空间,彼此相互隔离。
2.每个容器都单独的网卡、路由、IP等一些列基本的网络设施。
3.每个容器启动后,都会被分配一个独立的虚拟IP。
4.该模式会自动将宿主机上的所有容器,都链接到 #ip a 看到的docker0的虚拟网卡上。
5.外界主机不能直接访问宿主机内的容器服务,需要宿主机通过-p做端口映射后访问宿主的映射端口。
查看桥接网络模式docker0虚拟网卡的详细信息:
接下来我们以桥接的模式单独启动minio服务
docker run -d --name minio -v /etc/hosts:/etc/hosts --env-file /conf/storage/minioConf/minio --env-file /conf/storage/minioConf/miniocache minio:trinet server --console-address :19001
查看一下创建完容器之后会和之前的宿主机网络有什么不同
我们会发现多了一个虚拟网卡40: veth69f190c@if39,这个网卡接口建立在docker0之上。
再查看一下minio这个容器的网络资源,我们可以看到独立的IP,GATEWAY,Mac等资源。
我们启动它的时候没有给它暴露端口,所以它的端口为空,但我们配置文件中的端口分别为19000和19001,那我们能否正常访问服务呢(●’◡’●)')
先ping一下看看,查看路由发现会走docker0然后联通到主机,然后请求我们的19000端口,虽然认证没通过,但是证明了是能访问到服务的。
宿主机与容器通信是没问题的,那如果我再起一个容器呢?我从其他宿主机上访问该容器呢?
先试试再起一个容器minio2,看两个容器之间能否通信
启动第二个容器之后,又多了一张虚拟网卡建立在docker0之上。
他们之间的通信也是没有问题的。
试试其他宿主机的访问,发现无法ping通minio容器,直接请求宿主机1+19000端口也不行
为什么会造成这种差异呢?那是因为宿主机1与minio,minio2之间通过docker0连接了起来,而宿主机2虽然与宿主机1处于同一网段,但docker0是宿主机1内的虚拟网卡,宿主机2无法直接连通。那是不是意味着其他宿主机无法访问容器服务了呢?其实也能访问,我们上面启动容器的时候都是没有暴露端口启动的,只要我们启动容器的时候加上-p参数暴露端口就能访问到,现在我们加入一个minio3的容器并暴露端口试试看。请求是能到达minio3的。查看宿主机路由和ip转换规则,从19000和19001端口来的请求都会被转到172.17.0.4也就是minio3。
bridge网络模式示意图:
通过示意图,可以清晰的看到,docker容器在桥接模式下,会为每个容器分配单独的虚拟网卡、虚拟IP。然后再统一通过docker0虚拟网卡,统一和宿主机的enp4s0交互。
Bridge小结:
1、docker run 命令不带–net参数时,默认就是桥接模式。
2、桥接模式下,同一个宿主机内的容器,彼此的网络是互通的。
3、桥接模式下容器的虚拟IP,容器内部彼此之间可以访问,非宿主机的其他其他主机无法直接访问容器内部的服务。
4、注意:桥接模式下,虽然外界主机不能直接访问宿主机容器内部的服务,但是可以通过间接方式访问宿主机docker run -p时,对外暴露的映射端口。
比如:docker run -p 、19000:19000,其他主机可访问宿主机IP:19000端口,而不能直接访问宿主机内容器的19000端口。
host网络模式
特点:
1.host模式,它没有独立的网络空间。
2.host模式下的容器,完全和宿主机共用一个网络空间(端口、IP等),所以该模式下的容器不会虚拟出容器自身的虚拟网卡,也不会配置自己的虚拟IP。
3.host模式下的容器,除了网络和宿主机共享,其他的资源,如文件系统、进程列表等,容器之间依然是相互隔离的。
弊端:同一个端口,比如宿主机的80端口,只能被一个服务占用,如果被某个容器占用了,宿主机就不能用,后续的容器也不能用,直到优先抢到80端口的服务,停止提供服务(放弃80端口)。
Host模式下的容器启动后,不会创建新的网卡(桥接模式下的容器,会自动创建以veth开头的虚拟网卡)
docker inspect 查看Host模式下的网络详细信息
可以发现,Host模式开启的容器,容器自身是没有任何网络资源信息的,都是空的,它用的一切网络资源都是宿主机的,那么下面继续通过宿主机访问一下minio3吧。
尽管host模式下的minio容器没有任何网络资源,但是以该模式启动的容器,依然可以直接通过宿主机的IP(+端口,不同的服务,端口也不同)直接访问。
为什么呢?上面已经提及,Host模式运行的容器,用的一切网络资源,是霸占的宿主机的网络资源。访问容器,相当于访问的就是宿主机,给人的感觉就是:“宿主机就是容器,容器就是宿主机”。这种模式下,从请求的角度来看其实已经可以理解为,服务就是直接在宿主机上运行。然而除了网络资源,容器霸占的是宿主机的,容器之间的其他资源依然是相互隔离的,如文件系统、进程列表等。
host模式示意图:
host模式小结
Host模式的优点和缺点,都十分明显,容器内的服务只要部署成功,可以被同一网段内的局域网的其他任一主机访问,给人的错觉就是“宿主机就是容器,容器就是宿主机”。缺点就是,一个端口只能被一个服务占用,且容器的网络也缺少隔离性,故该使用场景十分有限。
因为该模式,不是默认的网络模式,所以在docker run的时候,要添加参数–net=host 或者 --network=host 来手动指定。
container网络模式
该模式≈bridge+host的混合模式,指定一个容器以bridge方式启动,后面容器启动时指定网络模式为container,它们自动共享第一个容器的网络资源。
特点
1.新创建的容器,仅同前面已存在的容器,共享网络空间,不与宿主机共享网络。
2.新创建的容器,不会有自己的虚拟网卡和IP,后面新创建容器的网络资源用的是上一个容器的。
3.新创建的容器,仅仅是网络和第一个容器共享,其他资源彼此还都是相互隔离的。
弊端:第一个指定容器服务一旦停掉,后续的容器也没有办法继续运行
模式探索
第一个minio容器以bridge网络模式启动,然后查看宿主机网络信息
第二个tomcat容器,以container网络模式启动,然后再ip a 查看网卡信息
乌龙了,没起得来,第一个容器已经占用了19000和19001了
换成用tomcat镜像起一下看看,发现网卡信息没有被改变
查看两个容器的网络资源,会发现bridge的容器网络资源都正常,container的容器网络资源为空
这两者都可以通过minio的ip去访问 只是端口不同
container网络模式图解
container模式小结
1、第二个容器以container网络模式启动后不会有网卡变化,网络会完全托管给指定的第一个容器,相当于第一个容器的主机模式。
2、container模式,docker run的时候,不能使用-p,因为-p是手动指定端口,而container模式的ip和端口是不受container模式的容器自身控制,它的IP和端口,相当于完全委托给第一个以桥接方式启动的容器了。
如果你不小心带了-p 8080:8080这个参数,你将看到这个错误:docker: Error response from daemon: conflicting options: port publishing and the container type network mode.
另外:–net=container后面直接跟冒号,冒号后面是它所依靠的以桥接方式启动的指定容器,即为:–net=container:nginx_Num1 ,其中nginx_Num1是上一步以bridge方式启动的第一个指定的容器。
none网络模式
这种模式就是一个光秃秃的容器,没有任何网络资源,不能和任何其他容器还有 宿主机之间进行正常的访问互动。犹如一个自闭症患者活在自己的世界里。
自定义网络模式
自定义网络需要通过docker network create进行创建,如果创建时不指定网络模式,默认就是bridge桥接模式。
创建bridge网络
自定义名字为mynet的网络,subnet指定子网网段(不能与其他网卡的网段重叠)
再创建三个容器
minio1:默认网络
minio2:默认网络
minio3:mynet
然后给minio2添加mynet
docker network connect mynet minio2
查看网络情况,minio1就和上面讲bridge的时候看到的一样,让我们看一下minio2的,可以看到minio2有两个网络分别是17.0.3和18.0.3
minio3的网络信息
再查看宿主机的网络信息可以看到,在通过docker network create 命令创建新的网络模式,并指定–subnet子网网段时,会自动创建新的虚拟网卡。
这两者之间会有差异吗?他们中间虽然有自定义网络,但网络模式好像都是bridge。
通过实践,发现还是有区别的。
网络方面的差异
默认网络docker0:网络中所有主机间只能用IP相互访问。
自定义网络(bridge):网络中所有主机除ip访问外,还可以直接用容器名(container-name)作为hostname相互访问。
创建overlay网络
dockers还有一种非常重要的网络模式 overlay网络模式。这种网络模式与之前的所有网络模式都不同,之前的网络模式都只能同一宿主机之间的容器与容器之间,甚至只能自己玩自己的。
overlay模式可以将多个宿主机上的容器连接到同一个网络中。这意味着容器可以通过Overlay网络进行透明的跨主机通信,就好像它们在同一个物理网络上一样。
特点
-
多主机通信:Overlay网络允许位于不同Docker宿主机上的容器之间进行通信,无论这些宿主机在物理网络上的位置如何。
-
跨主机连接:Overlay网络可以跨越多个Docker宿主机,创建一个虚拟的网络层,它隐藏了底层主机的物理网络细节。
-
容器扩展性:使用Overlay网络,可以轻松地添加、移除或迁移容器,而无需调整底层网络配置。
-
安全性:Overlay网络支持加密和认证,确保跨主机容器之间的通信是安全的。
创建overlay网络必须先初始化swarm集群,并且必须在swarm集群的主节点上
创建swarm集群后查看docker网络,我们发现,多了两个网络,一个是docker_gwbridge,一个是ingress
docker_gwbridge网络是当前节点和外网通信的门户,它是一个虚拟ip,宿主机会通过路由转发的方式将网络转发到docker_gwbridge从而实现容器与外界的通信。
ingress是swarm集群中与容器通信的overlay网络,在这个网络中使用vxlan(Virtual Extensible LAN)技术将多个宿主机上的容器连接到同一个网络中,从而实现容器通过overlay网络进行透明的跨主机通信。
overLay 如何通信:
-
创建Overlay网络后,Docker会在每个主机上创建一个虚拟网络的子网段,并分配给Overlay网络。
-
当容器加入Overlay网络时,Docker会为其分配一个虚拟IP地址,并更新主机的路由规则。这样,容器与容器之间可以直接使用虚拟IP地址进行通信。
-
Docker使用VXLAN(Virtual Extensible LAN)协议来实现Overlay网络的跨主机通信。VXLAN在底层网络上封装容器的数据包,使其能够跨主机传输。
-
当容器需要与其他主机上的容器通信时,Docker会将数据包封装在VXLAN中,并通过底层网络将其发送到目标主机。
-
目标主机上的Docker解析VXLAN包,提取容器数据包,并将其传递给目标容器。
通过这种方式,Overlay网络使得分布式应用程序中的容器可以方便地进行跨主机通信,而不必手动配置网络或关注底层网络细节。
适用场景:
-
多主机容器编排:Overlay网络使得在多台主机上运行的容器可以以一个逻辑网络的形式互相通信,这对于分布式应用程序和容器编排工具(如Docker Swarm和Kubernetes)非常有用。
-
跨数据中心通信:如果有多个数据中心,Overlay网络可以帮助容器在不同的数据中心之间建立连接,使得跨地理边界的容器之间可以安全、可靠地通信。
与bridge的区别和差异
-
Bridge网络适用于单主机上的容器通信,而不涉及多个主机之间的跨主机通信。
-
每个主机上都有一个名为
docker0
的虚拟网桥,作为宿主机上所有容器的默认网络接口。 -
Bridge网络使用IP地址和端口映射来实现容器之间以及容器与宿主机之间的通信。
关于overlay网络的更详细内容,细节可以查看《docker swarm 网络架构》这篇文档。
macvlan网络模式:
macvlan 本身是 linxu kernel 模块,其功能是允许在同一个物理网卡上配置多个虚拟网卡,即多个 interface,每个 interface 可以配置自己的 IP。macvlan 本质上是一种网卡虚拟化技术。
macvlan 的最大优点是性能极好,相比其他方式,macvlan 不需要创建 Linux bridge,而是直接通过interface 连接到物理网络。
使用macvlan模式需要打开宿主机网卡的混杂模式
分别在node1和node2创建macvlan网络
创建完macvlan网络后可以看到宿主机网络中并没有像桥接网络一样出现新的网络接口
然后再分别在两台机器上用macvlan创建容器试试看
查看docker日志,发现minio服务无法连接宿主机上的存储集群,进入容器分别ping宿主机和处于同一macvlan网络的另一容器,发现只有同网段下是通的,宿主机不通。
macvlan网络模式其实也不是不能容器和宿主机通信,只是可能需要重新配置路由转发等,会比较麻烦。
而且配置了之后和docker swarm的overlay网络相比,还丧失了容器管理的灵活性,计算节点压力过大的情况下无法对计算节点进行扩容。
docker swarm overlay 网络与macvlan网络对比:
overlay:
swarm集群搭建完成,网络就自动创建好了可以直接使用。
提供跨多个宿主机的容器网络连接。
支持服务发现和负载均衡,对于容器管理,容器的扩缩容都非常友好。
劣势在于网络方面的层级相对比较复杂,容器与宿主机之间需要通过路由转发等,它的网络链路会比macvlan更长,所以相对来说会有一定的性能开销。
macvlan:
允许容器直接连接到物理网络,而且每个容器可以具有独立的mac地址。
macvlan 是一种网卡虚拟化技术,能够将一张网卡虚拟出多张网卡。
在 Docker 中,macvlan 只支持 bridge 模式。
相同 macvlan 可以通信,不同 macvlan 二层无法通信,可以借助三层路由完成通信,但配置起来较为复杂。