八、网络管理
于2021年10月6日重新编辑
一、容器网络介绍
容器网络分为以下五种网络类型
- None
- host
- bridge
- user-defined
- container
dokcer在安装时就会自动创建三个网络,使用如下命令查看
dokcer network ls
下面分别介绍这五种网络类型,我的宿主机IP为10.154.0.110
二、五种网络类型
2.1 None
1)简介
什么都没有的网络,该网络的容器下只有lo网卡,即本机127.0.0.1,是一个与世隔绝的单机环境。
可使用参数--net=none
指定使用none网络
通常用于对安全要求高且不需要联网的容器使用,如生成随机密码的容器。
2)配置none网络
docker run -it --network=none busybox
可以看到处于none网络环境的容器只有lo网卡,无法与外部通信,也无法与其他容器通信。
2.2 host
1)简介
直接使用宿主机的IP地址。
可使用参数--net=host
指定使用host网络
通常用于对网络传输要求较高的网络环境,这样可以让容器直接访问网络,而不是通过宿主机转发。
2)配置host网络
docker run -it --network=host busybox
#查看刚创建的busybox的IP地址
docker exec a7 ifconfig
查看处于host网络的容器,会发现它使用了宿主机的网络环境,即ens33网卡
我们再创建一个nginx容器,访问宿主机IP地址
docker run -itd --network=host nginx
curl http://10.154.0.110
可以发现host网络的容器确实使用的是宿主机的IP,占用的是宿主机的端口。
注意:使用host网络最好使用-p指定映射端口,如果不指定则需要检查宿主机的端口跟容器的端口是否冲突,冲突会造成容器服务无法访问。
可参考:host网络介绍
2.3 bridge
1)简介
默认网络模式,容器的桥接模式,会创建一个名为docker0的虚拟网卡,所有处于该网络的容器都挂到docker0上,通过docker0代为转发。相当于VM的NAT模式,IP地址段默认为172.17.0.0/16,可供使用2^16-2个IP地址。
可使用参数--net=bridge
指定
最常用的网络模式,该网络模式下,需要将容器服务端口映射到宿主机才能进行访问,安全性较高。
bridge网络如下图所示
2)配置bridge网络
#安装brctl工具,方便查看网络环境
yum install bridge-utils -y
brctl show
此时还没有创建任何bridge网络的容器,所以interfaces是空的
#创建一个busybox容器,不写网络默认为bridge
docker run -it busybox
进入容器查看网络环境如下
可以看到分配的IP地址为172.17.0.2,接口为veth9e4f6el,此接口挂在docker0虚拟网卡上。
查看宿主机网络环境,会发现多出一张虚拟网卡,此为容器的网卡
2.4 user-defined
1)简介
用户自定义网络,docker提供三种自定义网络驱动,分别为bridge、overlay和macvlan。
其中overlay和macvlan用于创建跨主机网络,这个以后介绍。
用户自定义网络创建的bridge与普通bridge网络不同的是,自定义网络中创建的容器可以通过容器名或者主机名互通,这是因为自定义网络中的容器内部的hosts文件做了ip与主机名解析。
可通过docker network create
创建自定义网络
2)配置user-defined网络
docker network create --driver bridge my_net
brctl show
查看my_net配置信息可以多了一张br-d035b8dfefa4网卡,该网卡的地址段为172.18.0.0/16
查看my_net网络配置信息
docker network inspect my_net
创建指定IP网段
docker network create \
--driver bridge \
--subnet 172.22.16.0/24 \
--gateway 172.22.16.1 my_net2
运行容器使用指定的网络
docker run -itd --network=my_net2 busybox
运行容器使用指定的IP
docker run -itd --network=my_net2 --ip 172.22.16.8 busybox
只有使用--subnet创建的网络才能指定静态IP地址,否则会报错
此时网络拓扑结构如下
容器 | IP | 网络 |
---|---|---|
busybox1 | 172.16.0.2 | 默认 |
busybox2 | 172.22.16.2 | my_net2 |
busybox3 | 172.22.16.8 | my_net2 |
此时172.22.16.0网段能互相ping通,处于172.17.0.1的容器无法ping通,查看ip router
,跟iptables-save
,发现是因为iptables丢弃了docker0跟br-xxxxx之间的流量。
如果要让他们互相通信则可以使用connect实现,命令如下
docker network connect my_net2 2eadced8f4ac
会发现busybox1容器多出一张网卡,IP为172.22.16.3,此时的busybox1相当于双网卡,也就能跟busybox2和busybox3通信了
此时的网络环境如下所示
容器 | IP | 网络 |
---|---|---|
busybox1 | 172.16.0.2/172.22.16.3 | 默认/my_net2 |
busybox2 | 172.22.16.2 | my_net2 |
busybox3 | 172.22.16.8 | my_net2 |
2.5 container
1)简介
新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。
这种模式可以节约一定的网络资源,也就是IP地址。
可使用参数--net=container指定
2)配置container网络
docker run -d -it --name=web1 httpd
docker run -it --network=container:web1 busybox
这样busybox容器就是使用的httpd网络命名空间,bosybox可以访问127.0.0.1访问到web1的http服务。
可参考:container网络模式
三、容器网络原理
3.1 容器访问外部网络原理
我们创建一个容器busybox,会发现它默认就能访问外网
docker run -it busybox
ping www.baidu.com
使用iptables查看,会发现网桥docker0收到来自172.17.0.0/16网段的包会交给MASQUERADE处理,MASQUERADE会将包的源地址替换为宿主机的地址发送出去,做一次网络地址转换。
iptables -t nat -S | grep docker0
查看路由,默认路由是从ens33接口出去的
ip router
我们开三个会话窗口,监控icmp流量包
#窗口一
tcpdump -i docker0 -n icmp
#窗口二
tcpdump -i ens33 -n icmp
#窗口三
docker run -it busybox
ping www.baidu.com
可以发现docker0收到busybox的ping包,源地址为容器IP172.17.0.2,交给MASQUERADE处理,在ens33接口上,我们看到ping包源地址变为了10.154.0.110,宿主机的IP地址。
结果如下
- busybox发送Ping包:172.17.0.2-->www.baidu.com
- docker0收到包,发现是访问外网的,交给NAT处理
- NAT将源地址转换为ens33接口的IP,即宿主机IP:10.154.0.110-->www.baidu.com
- ping包从ens33接口出去,到达www.baidu.com
3.2 外部网络访问容器原理
使用的端口映射,具体看这篇。
下图环境为,宿主机IP:10.0.2.15,容器IP:172.17.0.3,端口映射为容器80映射到宿主机32773
总结
- docker-proxy监听宿主机32773端口
- 当有访问10.0.2.15:32773端口时,docker-proxy转发给容器172.17.0.3:80
- 容器172.17.0.3相应请求并返回处理结果
四、命令总结
4.1 创建None网络
docker run -it --network=none busybox
4.2 创建host网络
docker run -it --network=host busybox
4.3 创建bridge网络
#默认就是bridge
docker run -it busybox
docker run -it --network=bridge busybox
4.4 创建user-defined网络
#创建自定义bridge网络,名为my_net
docker network create --driver bridge my_net
#创建指定IP网段的自定义bridge网络
docker network create \
--driver bridge \
--subnet 172.22.16.0/24 \
--gateway 172.22.16.1 my_net2
#创建使用my_net网络的容器
docker run -itd --network=my_net busybox
#创建使用指定IP地址的容器
docker run -itd --network=my_net --ip 172.22.16.8 busybox
使用自定义创建的bridge网络,自动会在/etc/hosts做解析,能互相ping通容器名,这是跟直接创建bridge网络不一样的地方。
4.5 创建container网络
docker run -d -it --name=web1 httpd
docker run -it --network=container:web1 busybox
4.6 查看my_net网络信息
docker network inspect my_net
4.7 查看容器网络环境
docker network ls
4.8 查看容器IP地址
docker inspect -f {{".NetworkSettings.Networks.bridge.IPAddress"}} f428149ca2cf
4.9 查看容器网关
docker inspect -f {{".NetworkSettings.Networks.bridge.Gateway"}} f428149ca2cf
五、参考资料
《每天五分钟玩转docker容器技术》第5章