Docker容器

Docker学习高级篇03-Docker网络配置模式详解

本文主要是介绍Docker学习高级篇03-Docker网络配置模式详解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

0x00 docker网络模式——bridge

30个人用各自的电脑和电脑屏幕看电影

Docker服务默认会创建一个docker0网桥(其上有一个docker0内部接口),该桥接网络的名称为docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过docker0网桥相互通信

docker network inspect bridge | tail -n 20
docker network inspect bridge | grep name

1、Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Dcoker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信

2、Docker run的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是eth0,在宿主机可以看到docker0和自己create的network(后面讲)eth0、eth1、eth2...代表网卡一,网卡二,网卡三....,lo代表本地回环。

3、网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配

3-1、整个宿主机的网桥模式都是docker0,类似于一个交换机有一堆接口(veth),在本地主机和容器内分别创建一个虚拟接口,并让他们彼此接通。(这样一对接口叫veth pair)

3-2、每个容器实例内部也有一块网卡,每个网卡接口叫eth0

3-3、docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。

通过上述,将宿主机上的所有容器都链接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的IP,此时两个容器的网络就是互通的。

image-20220130222431249

1、演示

docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --name tomcat81 billygoo/tomcat8-jdk8
docker ps - n 2

进入其中一个容器,再次查看自己的网卡。

image-20220130222140246

2、bridge总结

宿主机——veth

容器网卡——eth0

两两匹配,veth统一由docker0接管

image-20220130222311442

0x01 Host模式

30个人,在电影院中看一个大屏幕

直接使用宿主机的IP地址与外界进行匹配,不再需要额外进行网桥NAT转换。

容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace,容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。

image-20220130225316119

我们可以通过docker network inspect来查看

image-20220130230129553

image-20220130230224966

案例

docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8	#这样的写法不正确,因为host模式默认使-p无效

image-20220130225556721

为什么不被推荐呢?docker启动时指定--network=host-net=host,如果还指定了-p映射端口,那这个时候就会有此警告。并且通过-p设置的参数将不会起到任何作用。端口号会以主机端口号为主,重复时递增。可以看到下图,就是没有任何的端口映射关系。

image-20220130225927779

解决:解决的办法就是使用docker的其他网络模式,例如--network=bridge,这样就可以解决问题,或者直接无视。。。

那么问题来了,没有-p设置的端口,如何访问启动的tomcat??

在CentOS里面用默认的火狐浏览器访问容器内的tomcat83看到访问成功,因为此时容器的IP借用主机的,所以容器共享宿主机网络IP,这样的好处就是外部主机与容器可以直接通信。

#去掉了-p参数
docker run -d  --network host --name tomcat83 billygoo/tomcat8-jdk8	
#访问http://宿主机ip:8080,即可访问到tomcat

0x02 none 模式

30个人不看电影,用自己的电脑看还是去电影院看,没有定下来。

在none模式下,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo,需要我们自己为Docker容器添加网卡

禁用了网络设置,只有lo标识。

image-20220130231101051

docker network inspect
docker run -d -p 8084:8080 --network none --name=tomcat84 billygoo/tomcat8-jdk8

image-20220130231015375

0x03 container模式

30个人用各自电脑、各自电脑屏幕来看电影,突然有一个人的电脑坏了,和旁边的人一起看。

说白了,我借用别人的。两张嘴共用一个吸管喝奶茶。

新建的容器和已经存在的一个容器共享一个网络IP配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP。而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。

image-20220130231436371

案例

docker run -d -p 8085:8080 		     --name tomcat85 billygoo/tomcat8-jdk8
docker run -d -p 8086:8080 --network container:tomcat85 --name tomcat86 billygoo/tomcat8-jdk8

但是当我们输入完成后,会发现出现了问题,这是一个坑!

image-20220130231917343

相当于tomcat86和85公用同一个IP同一个端口,导致冲突,本案例使用tomcat演示不合适。

我这里有一个问题,就是为什么bridge的时候,开两个tomcat没有冲突?

这就涉及到了一个IP多个端口的问题了。当时在学习建立网站的时候,一个IP可以建立多个网站,使用不同的端口即可。那么bridge,每个容器都有自己独立的IP,当然就不会冲突了。

换一个镜像演示:Alpine

Alpine Linux是一款独立的、非商业的通用Linux发行版,专为追求安全性、简单性和资源效率的用户而涉及,可能很多人没听说过这个Linux发行版,但是经常用Docker的朋友可能都用过,因为他小,简单、安全而著称。所以作为基础镜像是一个非常好的选择,可谓是麻雀虽小五脏俱全,镜像非常小巧,不到6M的大小,所以特别适合容器打包。

docker search alpine --limit 5
docker pull alpine
docker run -it 	  --name=alpine1 alpine /bin/sh		#NOTICE!!!!IS /bin/sh!!
docker run -it --network container:alpine1 --name=alpine2 alpine /bin/sh

image-20220130233044797

当alpine1停掉后,alpine2的网直接就没了

image-20220130233242632

0x04 自定义网络

docker link,是一个过时的技术。不用管了。已经被自定义网络替代了。

我们都知道了,Docker网络默认三种配置,但是为什么要有自定义网络呢?

image-20220130233420218

希望所有的容器分门别类,井井有条,在各自的网络里面和谐共存,并且能够完成网络之间的通信。之前的问题:1、容器间的互联和通信以及端口映射 2、容器IP变动的时候可以通过服务名直接网络通信而不受到影响。

1、使用自定义网络前

1、运行两个tomcat容器,默认网络bridge

docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --name tomcat82 billygoo/tomcat8-jdk8
docker exec -it tomcat81 bash
docker exec -it tomcat82 bash

2、两个机器互相ping,能够ping通,没任何毛病

image-20220131001344100

3、ping服务名,失败。

image-20220131001535447

这就是不使用自定义网络的问题,无法ping通服务名。可能会有人说了:谁TM ping服务名啊,ping IP不行么?

问题

之前我们试验过,docker环境中的各种主机IP是会发生变化的,即当此容器坏了,再启动一个容器,IP地址是会变的。所以我们必须保证服务能够ping通。

2、使用自定义网络之后

1、自定义桥接网络,自定义网络默认使用的是桥接网络bridge

2、新建自定义网络

docker network ls 
docker network create zzyy_network

image-20220131010418236

3、新建容器加入上一步新建的自定义网络

docker run -d -p 8081:8080 --network zzyy_network --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --network zzyy_network --name tomcat82 billygoo/tomcat8-jdk8

4、互相ping测试,成功

docker exec -it tomcat81 bash
docker exec -it tomcat82 bash
ping tomcat82
ping tomcat 81

在工作上一定要写死服务名,不能写死IP,除非你能保证地球不爆炸,IP不会变。多个docker服务群一定要写死服务名。

但是为什么加入自定义就能ping通服务名?

老师没有解释这个,但是看了一条弹幕说的挺有道理:

自定义网桥的容器会开启自己的dns,把名称和IP的对应关系发送到docker维护的dns里,docker里有了dns信息,自然可以做地址转换了,就这么easy

3、结论

重要的事情说三遍:

自定义网络本身就维护好了主机名和ip的对应关系(ip和域名即服务名都能通)

自定义网络本身就维护好了主机名和ip的对应关系(ip和域名即服务名都能通)

自定义网络本身就维护好了主机名和ip的对应关系(ip和域名即服务名都能通)

这篇关于Docker学习高级篇03-Docker网络配置模式详解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!