本篇将讲述Docker网络的一些概念,以便您在设计和部署应用程序时充分利用到这些功能。前端
首先,Docker的网络子系统是可插拔驱动式的,默认状况下存在或支持多种网络接口,如bridge、host、overlay、macvlan以及none类型的网络接口。web
接下来,咱们先来探讨下bridge(桥接)网络模式docker
bridge是docker默认的网络模式,若是不指定类型,则这是您正在建立的网络类型,bridge模式会为每个容器分配一个Network Namespace、IP等,并将容器的网络链接到一个网桥(docker0)上。数据库
特色:同一个宿主机上全部容器默认会在同一个网段(默认网段:172.17.0.0/16)下,且相互之间能够通讯以及访问外部网络(前提是宿主机能够访问外部网络)。后端
网桥就是在多个网段之间转发流量的链路层设备。网桥能够是运行在主机内核中的软件或者硬件设备。缓存
Docker使用的是软件网桥,容许链接在同一网桥的容器间进行通讯,同时提供与未链接到网桥网络的容器进行隔离。Docker网桥会自动设置相关规则(用iptables),不一样网桥上的容器不能直接相互通讯。安全
网桥适用于在同一个Docker守护程下的容器。对于在不一样Docker守护进程下运行的容器之间的通讯,能够在宿主机上添加路由,也可使用overlay网络。网络
当启动Docker daemon时,会自动建立默认的网桥网络(docker0)而且还会启动iptables来设置您的访问规则。您能够建立用户自定义的网桥网络,用户自定义的网桥网络优于默认的网桥(docker0),特色以下:架构
一、用户自定义的网桥在容器化应用程序之间提供了更好的隔离性和互操做性。ide
链接在同一网桥下的容器同属一个网络,所以全部端口能够互访,但对外部网络是不公开的,这使得容器化应用程序能够轻松地相互通讯,同时提升了安全性。
想象一下,一个带有web前端和后端,另外还有数据库的应用架构(用户<-->web入口<-->后端应用<-->数据库)。外部网络只须要访问web前端(如80端口),但只有后端应用须要访问数据库。若使用用户自定义的网桥,只须要对外开放web端口,数据库不须要对外开听任何端口,先后端均可以经过用户自定义的网桥来访问数据库。
二、用户自定义的网桥提供了容器之间的自动DNS解析。
在默认网桥上建立的容器,相互访问时只能经过IP地址,除非您使用--link选项,但--link是须要在容器的两个方向上建立,对于须要通讯的两个以上的容器,这会变得复杂。而在用户自定义的网桥网络上,容器间能够经过名称或别名相互解析。
回想一下,在使用物理主机或者VM主机时,咱们应用程序的配置文件中通常用hosts中的主机名称或者IP,而如今在容器中,使用自定义网络,咱们只要改写成容器名就行了,不须要太关注主机名称或者IP,是否是很开森。
三、使用用户自定义网桥的容器,支持随时断开或链接到不一样的(用户自定义)网络。
在容器的生命周期中,您能够动态切换容器间的网络链接,好比,您建立了自定义my-net01和my-net02桥接网络,这两个网络中的容器能够互相动态切换的。若是您是经过默认网桥建立的容器,也能够切换到自定义网桥中,而没必要删除容器重建。
注:这里在实际验证过程当中,貌似与官方文档描述有出入。
四、每一个用户自定义的网络都是建立了一个可配置的网桥。
若是全部容器都使用默认网桥网络,虽然说能够修改配置,但全部容器都使用相同的设置,例如MTU和iptables规则。此外,配置默认网桥网络须要重启Docker进程。
如果使用docker network create建立和配置用户自定义的网桥网络。若是不一样的应用程序组有不一样的网络需求,则能够在建立每一个用户定义的网桥时分别对其进行配置。
五、使用默认网桥的容器之间可共享环境变量。
起初,在两个容器之间共享环境变量的惟一方法是使用--link。这种类型的变量共享在用户自定义的网络中是不可能的。然而,如今却有更好的方法来共享环境变量。
(1)、多个容器可使用Docker的卷(Volume)来装载包含共享信息的文件或目录。
(2)、多个容器可使用docker compose来一块儿启动,compose文件中能够定义共享变量。
(3)、可使用swarm服务来代替独立的容器,并共享密钥和配置。
管理自定义网桥网络
一、使用docker network ls 查看默认支持网络
# docker network ls
NETWORK ID NAME DRIVER SCOPE
e22a6ab223fe bridge bridge local
15b417347346 host host local
5926c0bd11d0 none null local
二、使用docker network create 建立自定义网桥网络
# docker network create my-web-net01
# docker network ls
NETWORK ID NAME DRIVER SCOPE
e22a6ab223fe bridge bridge local
15b417347346 host host local
899362727b48 my-web-net01 bridge local
5926c0bd11d0 none null local
能够看到,咱们并无指定--driver=bridge来建立,由于默认就是bridge模式,固然,您也能够指定自定义网桥的子网、IP范围、网关和其余项,例如:
# docker network create --driver=bridge --subnet=172.23.10.0/24 my-web-net02
或者再细化一点
# docker network create \
--driver=bridge \
--subnet=172.24.0.0/16 \
--ip-range=172.24.10.0/24 \
--gateway=172.24.10.254 \
my-web-net03
删除自定义网桥网络
# docker network ls
NETWORK ID NAME DRIVER SCOPE
e22a6ab223fe bridge bridge local
15b417347346 host host local
899362727b48 my-web-net01 bridge local
49352768c5dd my-web-net02 bridge local
7e29b5afd1be my-web-net03 bridge local
5926c0bd11d0 none null local
# docker network rm my-web-net01
或者指量删除
# docker network rm $(docker network ls -f name=my-web -q) #该命令含义是将名字包含my-web的网络列出并删除
同一个自定义网桥中的容器经过容器名互相访问
一、建立自定义网络my-web-net01
# docker network create my-web-net01
二、建立容器t0一、t02并使用my-web-net01网络
# docker run -idt --network=my-web-net01 --name t01 busybox /bin/sh
# docker run -idt --network=my-web-net01 --name t02 busybox /bin/sh
三、使用ping命令分别从t0一、t02使用容器名进行互ping,验证网络的互通性
# docker exec -it t01 ping t02
# docker exec -it t01 ping t02
结论:同一自定义网络中的容器能够经过容器名互相访问
在默认网桥中的容器不能经过容器名互相访问
一、在默认网桥中建立t0三、t04容器
# docker run -idt --name=t03 busybox /bin/sh
# docker run -idt --name=t04 busybox /bin/sh
二、使用ping命令分别从t0三、t04使用容器名进行互ping,验证网络的互通性
# docker exec -it t03 ping t04
ping: bad address 't04'
# docker exec -it t04 ping t03
ping: bad address 't03'
三、使用ping命令分别从t0三、t04使用ip地址互ping,验证网络的互通性
# docker exec -it t03 ifconfig
# docker exec -it t04 ifconfig
# docker exec -it t03 ping 172.17.0.6
# docker exec -it t04 ping 172.17.0.4
结论:在默认网桥中的容器不能经过容器名互相访问,但能够经过ip互访。
自定义网桥中的容器,能够动态切换容器间的网络链接
一、建立自定义网桥my-web-net02
# docker network create my-web-net02
二、将在my-web-net01网桥中的容器t02同时加到my-web-net02网络中,而后查看t02的网络,如图1.1所示,发现t02多了一个eth1网卡。
# docker network connect my-web-net02 t02
图1.1
三、将t02移出my-web-net01网络,而后,咱们再次查看t02的网络链接,如图1.2所示,发现只有eth1网卡了
# docker network disconnect my-web-net01 t02
四、再次验证t02是否还能与t01互通,如图1.3所示。
图1.3
结论:默认已经不能互通,即便用ip也不能,由于t01属于my-web-net01,t02属于my-web-net02。
五、将t02加回到my-web-net01网络,验证互通性,如图1.4所示。
# docker network connect my-web-net01 t02
图1.4
结论:t01与t02能够互通。
将默认网桥中的容器,加入到自定义网桥,验证互通性
一、将t03加入到自定义网桥my-web-net01中,并验证t03与t01和t04的互通性,如图1.5所示。
图1.5
二、将容器从某网络中移除再从新加入网卡名会发生变化,如图1.6所示。
图1.6
总结
不论是自定义网桥仍是默认网桥中的容器,均支持动态切换容器间的网络链接,另外,容器在作网络切换时网卡名称会发生变化(重启容器后名称会恢复),这对于须要绑定网卡名称的应用会存在问题,好比阿里的tair缓存。