第四阶段
时 间:2023年8月4日
参加人:全班人员
内 容:
Docker网络模型详解
目录
一、环境配置
(一)安装docker-ce(Linux安装Docker)
二、Docker网络基础
(一)端口映射
案例实验:
(二)端口暴露
(三)容器互联
案例实验:
(四)使用link参数
三、Docker网络模式
(一)Host模式
(二)container模式
(三)none模式
(四)bridge模式
(五)Overlay模式
一、环境配置
网络是激活Docker体系的唯一途径,如果Docker没有比较出色的容器网络,那么Docker根本没有如今的竞争力,起初Docker网络的解决方案并不理想,但是经过最近几年的发展,再加上很多云计算服务商都参与了进来,大批的SDN方案如雨后春笋般的冒了出来。
(一)安装docker-ce(Linux安装Docker)
CentOS系统下安装Docker可以有两种方式:
一种是使用curl获得Docker的安装脚本进行安装,
另一种是使用YUM仓库来安装Docker。主要注意的是目前Docker只能支持64位系统。
1、安装前准备:
[root@huyang1 ~]# iptables -F
[root@huyang1 ~]# setenforce 0
[root@huyang1 ~]# systemctl stop firewalld
保证可以访问互联网
[root@huyang1 ~]# ping www.baidu.com
[root@huyang1 ~]# ls /etc/yum.repos.d/
[root@huyang1 yum.repos.d]# yum clean all && yum makecache fast
[root@huyang1 ~]# wget -O
/etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@huyang1 ~]# yum -y install yum-utils
device-mapper-persistent-data lvm2
[root@huyang1 ~]# yum-config-manager --add-repo
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@huyang1 ~]# ls /etc/yum.repos.d/
[root@huyang1 ~]# yum -y install docker-ce
[root@huyang1 ~]# docker version 查看版本
[root@huyang1 ~]# systemctl start docker
[root@huyang1 ~]# systemctl enable docker
3、阿里云镜像加速器
阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台
[root@huyang1 ~]# cat << END > /etc/docker/daemon.json
{ "registry-mirrors":[ "https://nyakyfun.mirror.aliyuncs.com" ]
}
END
[root@huyang1 ~]# systemctl daemon-reload
[root@huyang1 ~]# systemctl restart docker
[root@huyang1 ~]# docker version
下载需要用到的镜像:
[root@docker ~]# docker pull nginx
[root@docker ~]# docker pull busybox
[root@docker ~]# docker pull mysql
[root@docker ~]# vim /etc/sysctl.conf
[root@docker ~]# sysctl -p
二、Docker网络基础
Docker目前对单节点的设备提供了将容器端口映射到宿主机和容器互联两个网络服务。
(一)端口映射
在Docker中容器默认是无法与外部通信的,需要在启动命令中加入对应的参数才允许容器与外界通信。
当Docker中运行一个Web服务时,需要把容器内的Web服务应用程序端口映射到本地宿主机的端口。这样,用户访问宿主机指定的端口的话,就相当于访问容器内部的Web服务端口。
案例实验:
1、-P选项,随机端口
使用-P选项时Docker会随机映射一个端口至容器内部的开放端口
[root@docker ~]# docker run -d -P --name nginx-test1 nginx
使用docker port可以查看端口映射情况
[root@docker ~]# docker port nginx-test1
访问测试:192.168.100.131:32768
[root@docker ~]# docker logs nginx-test1
查看映射的随机端口范围
[root@docker ~]#
cat /proc/sys/net/ipv4/ip_local_port_range
2、使用-p可以指定要映射到的本地端口。
Local_Port:Container_Port,任意地址的指定端口
端口映射参数中指定了宿主机的8000映射到容器内部的80端口,可以多次使用-p选项
[root@docker ~]# docker run -d -p 8000:80 --name nginx-test2 nginx
访问测试:192.168.100.131:8000
这种方式会映射到所有接口地址,所有访客都可以通过宿主机所有IP的端口来访问容器。
如下:查看宿主机当前的ip地址
访问测试:192.168.59.153:8000
Local_IP:Local_Port:Container_Port
映射到指定地址的指定端口
[root@docker ~]# docker run -d -p
192.168.100.131:9000:80 --name nginx-test3 nginx
访问测试:192.168.100.131:9000
访问测试:192.168.59.153:9000
Local_IP::Container_Port
映射到指定地址,但是宿主机端口是随机分配的
[root@docker ~]# docker run -d -p 192.168.100.131::80 --name nginx-test4 nginx
[root@docker ~]# docker port nginx-test4
访问测试:192.168.100.131:32770
指定传输协议:TCP
[root@docker ~]# docker run -d -p 80:80/tcp --name nginx-test5 nginx
[root@docker ~]# docker port nginx-test5
访问测试:192.168.100.131:80
(二)端口暴露
咱们之前讲过EXPOSE命令用于端口暴露,很多人会把端口暴露和端口映射混为一谈。
目前有两种方式用于端口暴露:
--expose和EXPOSE方式,这两种方式作用相同,但是--expose可以接受端口范围作为参数,例如--expose=2000~3000。
Dockerfile的作者一般在包含EXPOSE规则时都只提示哪个端口提供哪个服务。访问时还需要运维人员通过端口映射来指定。--expose和EXPOSE只是为其他命令提供所需信息的元数据。
通过docker inspect container_name查看网络配置:
[root@docker ~]# docker inspect nginx-test1
(三)容器互联
容器互联是除了端口映射外另一种可以与容器通信的方式。端口映射的用途是宿主机网络与容器的通信,而容器互联是容器之间的通信。
当前实现容器互联有两种方式:
一种是把两个容器放进一个用户自定义的网络中,
另一种是使用--link参数(已经弃用,即将删除的功能)。
为什么要使用一个单独的网络来连接两个容器呢?
设想一下后端容器需要调用一个数据库环境,数据库容器和后端服务容器如果使用上下文中的暴露端口或者映射端口来通信,势必会把数据库的端口也暴露在外网中,导致数据库容器的安全性大大降低,为了解决这个问题,docker允许用户建立一个独立的网络来放置相应的容器,只有在该网络中的容器才能相互通信,外部容器是无法进入这个特定网络中的。
一个容器可以同时加入多个网络,使用不同地址可以访问不同网络中的容器。
案例实验:
1、用户自定义的网络:
首先创建两个容器,命名为cont1和cont2
[root@docker ~]# docker run -itd --name=cont1 busybox
[root@docker ~]# docker run -itd --name=cont2 busybox
查看当前的IP信息:
Cont1pingcont2测试:
接下来创建一个独立的容器网络,这里使用bridge驱动(桥接模式),其他可选的值还有overlay和macvlan。
[root@docker ~]# docker network create -d bridge --subnet 172.25.0.0/16 demo_net
[root@docker ~]# docker network ls
使用--subnet和--gateway可以指定子网和网关,现在我们把cont2加入到demo_net中
[root@docker ~]# docker network connect demo_net cont2
[root@docker ~]# docker network inspect demo_net
使用docker network inspect可以查看网络中容器的连接状态。Container2已经在demo_net网络中,注意IP地址使自动分配的。
[root@huyang1 ~]# docker exec -it 9a /bin/sh
/ # ifconfig
对比发现,此时cont2已经有了172.25.0.0的网络
启动第三个容器:
[root@docker ~]# docker run --network=demo_net --ip=172.25.3.3 -itd --name=cont3 busybox
[root@docker ~]# docker network inspect demo_net
此时,有三个容器,cont1和cont2可以ping通,cont2和cont3可以ping通,而宿主机可以和三者任意ping通,详情如下图:
查看三个容器内部的网络:
[root@docker ~]# docker exec -it cont1 ifconfig
[root@docker ~]# docker exec -it cont2 ifconfig
[root@docker ~]# docker exec -it cont3 ifconfig
Ping测试:
【cont2】
[root@docker ~]# docker exec -it cont2 ping 172.17.0.2
[root@docker ~]# docker exec -it cont2 ping 172.25.3.3
【cont1】
[root@docker ~]# docker exec -it cont1 ping 172.17.0.2
[root@docker ~]# docker exec -it cont1 ping 172.25.0.2
[root@docker ~]# docker exec -it cont1 ping 172.25.3.3
【cont3】
[root@docker ~]# docker exec -it cont3 ping 172.17.0.2
[root@docker ~]# docker exec -it cont3 ping 172.25.0.2
[root@docker ~]# docker exec -it cont3 ping 172.17.0.3
Ps备注:
当发生三个容器cont1/2/3可以相互之间都能ping通,这时候,需要重启容器(systemctl restart docker),再开启测试!!!
(四)使用link参数
容器的连接(linking)系统是除了端口映射外另一种可以与容器中应用进行交互的方式。它会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息。
使用这个参数容器必须设置一个名字,也就是--name指定的值。
[root@docker ~]# docker run -itd --name test busybox
--link参数的格式: --link name:alias , 其中name是要链接的容器的名称,alias是这个链接的别名。
[root@docker ~]# docker run -itd --name=link --link test:test busybox
[root@docker ~]# docker exec -it link ping test
如果忘记设置名字可以通过docker rename来重命名容器,容器名字是唯一的。
此外--link还可以传递环境变量,实现在两个容器之间共享环境变量。
三、Docker网络模式
安装Docker时会自动创建3个网络,可以使用docker network ls命令列出这些网络。
[root@docker ~]# docker network ls
我们在使用docker run创建容器时,可以用--net选项指定容器的网络模式。
Docker有以下4种网络模式:
Host模式:使用--net=host指定。
Container模式:使用--net=container:NAME_or_ID指定。
None模式:使用--net=none指定。
Bridge模式:使用--net=bridge指定,默认设置。
(一)Host模式
Docker底层使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。
一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptables规则等都与其他的Network Namespace隔离。
一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Root Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。出于安全考虑不推荐使用这种网络模式。
我们在192.168.200.111/24的机器上用Host模式启动一个含有WEB应用的Docker容器,监听TCP 80端口。当我们在容器中执行任何类似ifconfig命令查看网络环境时,看到的都是宿主机上的信息。
而外界访问容器中的应用,则直接使用192.168.100.131:80即可,不用任何NAT转换,就如直接跑在宿主机中一样。
但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
[root@docker ~]# docker run -itd --net=host --name=host busybox
[root@docker ~]# docker exec -it host ifconfig
[root@docker ~]# ifconfig
Ps备注:两者一摸一样,相当于虚拟机的仅主机模式!
(二)container模式
这个模式可以指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。
新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。
同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
使用--net=container:container_id/container_name,多个容器使用共同的网络看到的ip是一样的。
[root@docker ~]# docker run -itd --name=con1 busybox
[root@docker ~]# docker exec -it con1 ifconfig
[root@docker ~]# docker run -itd --net=container:con1 --name=con2 busybox
[root@docker ~]# docker exec -it con2 ifconfig
Ps备注:类似于双胞胎,使用相同的网卡信息!
(三)none模式
在这种模式下,Docker容器拥有自己的Network Namespace,但是并不为Docker容器进行任何网络配置。
也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
使用--net=none指定,这种模式下不会配置任何网络。
[root@docker ~]# docker run -itd --name=none --net=none busybox
[root@docker ~]# docker exec -it none ifconfig
(四)bridge模式
bridge模式是Docker默认的网络设置,属于一种NAT网络模型,Docker daemon在启动的时候就会建立一个docker0网桥(通过-b参数可以指定),每个容器使用bridge模式启动时,Docker都会为容器创建一对虚拟网络接口(veth pair)设备,这对接口一端在容器的Network Namespace,另一端在docker0,这样就实现了容器与宿主机之间的通信。
在bridge模式下,Docker容器与外部网络通信都是通过iptables规则控制的,这也是Docker网络性能低下的一个重要原因。
使用iptables -vnL -t nat可以查看NAT表,在Chain Docker中可以看到容器桥接的规则。
[root@docker ~]# iptables -vnL -t nat
(五)Overlay模式
这是Docker原生的跨主机多子网的网络模型,当创建一个新的网络时,Docker会在主机上创建一个Network Namespace,Network Namespace内有一个网桥,网桥上有一个vxlan接口,每个网络占用一个vxlan ID,当容器被添加到网络中时,Docker会分配一对veth网卡设备,与bridge模式类似,一端在容器里面,另一端在本地的Network Namespace中。
容器A、B、C都在主机A上面,而容器D、E则在主机B上面,现在通过Overlay网络模型可以实现容器A、B、D处于同一个子网,而容器C、E则处于另一个子网中。
Overlay中有一个vxlan ID,值得范围为256~1000,vxlan隧道会把每一个ID相同的网络沙盒连接起来实现一个子网。