本节主要是介绍Docker默认的网络行为,包含创建的默认网络类型以及如何创建用户自定义网络,也会介绍如何在单一主机或者跨主机集群上创建网络的资源需求。
1、默认网络
当你安装了docker,她自动创建了3个网络,可以使用docker network命令来查看
这三个网络被docker内建。当你运行一个容器的时候,可以使用--network参数来指定你的容器连接到哪一个网络。
1)bridge网络
默认连接到docker0这个网桥上。
注:brctl命令在centos中可以使用yum install bridge-utils来安装
启动并运行一个容器
[root@localhost ~]# docker exec -it test1 /bin/bash
可以看到test1容器已经获取了一个地址172.17.0.3,和主机的docker0接口地址在同一个网络,并将主机的docker0接口地址设置为了网关。
在物理主机上,查看网桥docker0,可以看到已经多了一个接口。
Docker容器默认使用bridge模式的网络,其特点如下:
- 使用一个linux bridge,默认docker0。
- 使用veth对,一头在容器的网络namespace中,一头在docker0上。
- 该模式下Docker Container不具有一个公有IP,因为宿主机的IP地址与veth pair的IP地址不在同一个网段内。
- Docker采用NAT方式,将容器内部的服务监听的端口与宿主机的某一个端口port进行”绑定“,使得宿主机以外的世界可以主动将网络保存发送至容器内部。
- 外界访问容器内的服务时,需要访问宿主机的IP以及宿主机的端口port。
- NAT模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。
- 容器拥有独立、隔离的网络栈;让容器和宿主机以外的世界通过NAT简历通信
效果是这样的:
示意图如下:
在物理主机上查看iptables的nat表,可以看到在POSTROUTING链中做了地址伪装:MASQUERADE动作,这样容器就可以通过原地址转换NAT访问外部网络了。
通过iptables -t nat -vnL命令查看到:
可以使用docker network inspect bridge命令来查看bridge网络情况:
[root@localhost ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "d22bd827a7eb3206cd71bd7c60c4fe68b8ba068a2716abf89b7a5a3c68dd9635",
"Created": "2020-10-21T21:37:12.892688838+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
2)none网络模式:
网络模式为none,即不为Docker容器构造任何网络环境,不会为容器创建网络接口,一旦Docker容器采用了none网络模式,那么容器内部就只能使用loopback网络设备,不会再有其他的网络资源。Docker Container的网络模式意味着不给该容器创建任何网络环境,容器只能使用127.0.0.1的本机网络。
启动一个容器,设为none网络
[root@localhost ~]# dockerv run -it -d --network none --name test3 ubuntu /bin/bash
由于没有网络不能使用yum安装ip addr命令,所以不能查看网卡。
3)host网络模式
Host模式并没有为容器创建一个隔离的网络环境。而之所以称之为host模式,是因为该模式下的Docker容器会和host宿主机共享同一个网络namespace,故Docker Container可以和宿主机一样,使用宿主机的eth0,实现和外界的通信。换言之,Docker Container其特点包括:
- 这种模式下的容器没有隔离的network namespace
- 容器的IP地址同Docker host的IP地址
- 需要注意容器中服务的端口号不能与Docker host上已经使用的端口号相冲突
- host模式能够和其它模式共存
示意图:
例如,我们在192.168.22.7/24的机器上用host模式启动一个含有web应用的Docker容器,监听tcp80端口。当我们在容器中执行任何类似ifconfig命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用192.168.22.7:80即可,不用任何NAT转换,就如直接跑在宿主机一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
启动容器前,查看物理主机的httpd进程
启动一个容器:
[root@localhost ~]# docker run -itd --privileged --name test5 --network host centos:7 init
进入容器,安装httpd容器,并启动:
[root@localhost ~]# docker exec -it test5 /bin/bash
[root@localhost /]# yum -y install httpd
[root@localhost /]# systemctl start httpd
[root@localhost /]# echo "test docker host network" > /var/www/html/index.html
退出容器,在此查看httpd进程:
访问主机的80端口,可以访问到容器test5网站服务(注意防火墙):
[root@localhost ~]# firewall-cmd --add-port=80/tcp
success
4)container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进行列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
Container网络模式是Docker中一种较为特别的网络模式。这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的容器存在网络隔离。
注意:因为此时两个容器要共享一个network namespace,因此需要注意端口冲突情况,否则第二个容器将无法被启动
示意图:
运行一个容器:查看容器IP
启动另外一个容器,使用test5容器网络:
[root@localhost ~]# docker run -itd --name test6 --network container:test5 centos:7 /bin/bash
5f726c21a516f081212f0b6dee91f0e86ba30dd8eb1c88f2fc38ca8c04222e79
进入test6容器,查看网络情况,可以看到两个容器地址信息相同,是共享的