文章目录
创建容器网络,实现容器间通信。
Docker容器间的通信方式根据媒介可以分为:volume共享通信
、网络通信
等;根据通信范围也可以分为:同主机通信
和跨主机通信
等。而本文主要针对容器间的网络通信方法进行讨论。
1、Docker的网络驱动模型
Docker的网络驱动模型分类:
- bridge:Docker中默认的网络驱动模型,在启动容器时如果不指定则默认为此驱动类型;
- host:打破Docker容器与宿主机之间的网络隔离,直接使用宿主机的网络环境,该模型仅适用于Docker17.6及以上版本;
- overlay:可以连接多个docker守护进程或者满足集群服务之间的通信;适用于不同宿主机上的docker容器之间的通信;
- macvlan:可以为docker容器分配MAC地址,使其像真实的物理机一样运行;
- none:即禁用了网络驱动,需要自己手动自定义网络驱动配置;
- plugins:使用第三方网络驱动插件;
以上是Docker支持的几种网络驱动模型,它们都具有独特的特点和应用范围,为了更加详细地了解Docker的网络运行原理,下面挑选几种较为重要的网络模型进行研究。
2.、bridge
2.1 Docker的默认网桥
如上图所示为Docker中bridge
驱动模式的示意图,其中蓝色的模块表示主机上的网卡。当Docker启动时会自动在主机上创建一个虚拟网桥docker0
,使用默认网络模式创建docker容器时会自动创建一对儿veth pair
接口,一端连接在docker容器中(如图容器中的eth0
),一端连接在虚拟网桥docker0
上(如图veth
)。这种veth pair
是一种虚拟网络设备,主要用于不同namespace中(意味着网络隔离)的网络通信,它总是成对存在的。在这里可以把它想象成一对儿靠虚拟网线连接起来的两个虚拟网卡,一端连接着docker容器,一端连接着虚拟网桥docker0
。
通过这种方式,不同docker容器之间可以通过ip地址互相通信,也可以通过虚拟网桥访问主机上的网络eth0
(添加iptables规则,将docker容器对目标地址发出的访问通过地址伪装的方式修改为主机对目标地址进行访问)。
如果想要外界网络访问docker容器时,需要在docker容器启动时加上参数'-p [主机端口]:[容器端口]'进行端口映射,原理也是通过修改iptables规则将访问[主机端口]的数据转发到docker容器的[容器端口]中,但是这种做法也存在着占用主机有限的端口资源的缺点。
docker network ls
# 输出结果:
NETWORK ID NAME DRIVER SCOPE
e79b7548b225 bridge bridge local
666d5f1f459d host host local
d0d785cf4794 none null local
然后通过命令docker network inspect bridge
查看bridge网络的详细配置:
docker network inspect bridge
# 输出结果:
[
{
"Name": "bridge",
"Id": "e79b7548b225c3c80d0f70d0de0b5911ed70a7f39ac20f75a8ae71c5cef05b3a",
"Created": "2019-05-17T13:01:27.6581642Z",
"Scope": "local",
"Driver": "bridge", # bridge驱动模式
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16", # 子网,docker容器的IP范围
"Gateway": "172.17.0.1" # 网关,即docker0
}
]
},
...
省略
...
# 两个docker容器(一个mysql容器,一个Web服务容器)的网络配置
"Containers": {
# mysql容器
"d6f33e9bbd60e10d02dd2eebea424a7fc129d9646c96742ec3fe467833017679": {
"Name": "mysqld5.7",
"EndpointID": "32e900f33367e3570c416c43a5618bd7a742cf94f36799e92895951ed1784736",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16", # 容器的IP
"IPv6Address": ""
},
# 基于tornado的Web服务容器
"dd292d535d16bbfe5382e29486756f4dddfea8e9b10af769db61618d739c5c4e": {
"Name": "test_demo",
"EndpointID": "eaf8e294f7b54aa50c6e6b30ac91f63b1a0ccbc5b56d6fbdcfeacd0471b15eb3",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16", # 容器的IP
"IPv6Address": ""
}
},
"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": {}
}
]
由上述配置信息可以看出,docker网桥的网关的IP为"172.17.0.1",也即docker0
,而docker的子网为"172.17.0.0/16",docker将会为容器在"172.17.0.0/16"中分配IP,如其中的mysql容器
的IP为"172.17.0.2/16"、test_demo容器
的IP为"172.17.0.3/16"。由于不同容器通过veth pair
连接在虚拟网桥docker0
上,所以容器之间可以通过IP互相通信,但是无法通过容器名进行通信:
# 在test_demo容器中访问mysqld5.7容器(通过IP)
ping 172.17.0.2 -c 3
# 输出结果:
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.147 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.185 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.209 ms
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2057ms
rtt min/avg/max/mdev = 0.147/0.180/0.209/0.027 ms
# 在test_demo容器中访问mysqld5.7容器(通过容器名)
ping mysqld5.7
# 输出结果:
ping: mysqld5.7: Name or service not known
所以,默认的网桥bridge
上的容器只能通过IP互连,无法通过DNS解析名称或别名。假如我们在container1中部署了Web服务,在container2中部署了mysql,container1中的Web服务往往需要连接container2的mysql,这是只能靠IP进行连接,但是docker也无法保证容器重启后的IP地址不变,所以更好的方式是通过别名进行互联,在网络中加入DNS服务器,将容器名与IP地址进行匹配,省去了手动修改Web服务中连接mysql的IP的过程。
为了实现不同容器通过容器名或别名的互连,docker提供了以下几种:
- 在启动docker容器时加入
--link
参数,但是目前已经被废弃,废弃的主要原因是需要在连接的两个容器上都创建--link
选项,当互连的容器数量较多时,操作的复杂度会显著增加; - 启动docker容器后进入容器并修改
/etc/host
配置文件,缺点是手动配置较为繁杂; - 用户自定义
bridge
网桥,这是目前解决此类问题的主要方法;
2.2 用户自定义bridge
用户自定义bridge相对于使用默认bridge的主要优势:
- 用户自定义bridge可以在容器化的应用程序提供更好的隔离效果和更好的互通性: 这段话看似有些矛盾,但是其中
更好的隔离效果
是针对外界网络,而更好的互通性
则是指同一bridge
下的不同容器之间。还是以之前的分别部署了Web服务和mysql服务的两个容器container1、container2为例,container1只需要对外界网络暴露Web服务的80
端口,而负责后端的container2只需与container1互连,不需要对外暴露,有效地保护了后端容器的安全性,提高了容器对外的隔离效果。而同属于用户自定义bridge
的容器container1、container2之间自动将所有端口暴露,方便容器间进行无障碍的通信,而不会遭受到外界的意外访问。 - 用户自定义bridge在容器之间提供了自动DNS解析: 这也是本文讨论的重点,不同于默认bridge只能通过IP互连的限制,用户自定义的bridge自动提供了容器间的DNS解析功能,容器间可以通过容器名或别名进行通信。
2.2.1 如何使用用户自定义bridge
- 创建用户自定义bridge:
docker network create my-net # 创建了一个名为"my-net"的网络
- 将Web服务容器和mysql服务容器加入到"my-net"中,并观察变化:
docker network connect my-net test_demo # 将Web服务加入my-net网络中
docker network connect my-net mysqld5.7 # 将mysql服务加入my-net网络中
# 查看my-net的网络配置
docker network inspect my-net
# 输出结果(省略部分内容):
[
{
"Name": "my-net",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Config": [
{
"Subnet": "172.18.0.0/16", # my-net的子网
"Gateway": "172.18.0.1" # my-net的网关
}
]
},
"Containers": {
"d6f33e9bbd60e10d02dd2eebea424a7fc129d9646c96742ec3fe467833017679": {
"Name": "mysqld5.7",
"EndpointID": "7d0e8d70bb523cceb4d2d8d4e3f8231fc68332c70f7f9b4e5d4abccce2b31a65",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16", # mysql服务容器的IP,与之前不同
"IPv6Address": ""
},
"dd292d535d16bbfe5382e29486756f4dddfea8e9b10af769db61618d739c5c4e": {
"Name": "test_demo",
"EndpointID": "f7802f1af81e258f77e227609dfdcdf66c49f19776381eb8b0dca6d9e794ccad",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16", # Web服务容器的IP,与之前不同
"IPv6Address": ""
}
},
}
]
如上所示,用户自定义网络my-net
的子网为"172.18.0.0/16",所以两docker容器在my-net
网络中的IP分别为:"172.18.0.3/16"、"172.18.0.2/16",与之前的"172.17.0.2/16"、"172.17.0.3/16"不同。
- 通过容器名或别名互连: 进入到Web服务器container1中连接container2:
ping mysqld5.7 -c 3
# 输出结果:
PING mysqld5.7 (172.18.0.3) 56(84) bytes of data.
64 bytes from mysqld5.7.my-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from mysqld5.7.my-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.145 ms
64 bytes from mysqld5.7.my-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.143 ms
--- mysqld5.7 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2048ms
rtt min/avg/max/mdev = 0.066/0.118/0.145/0.036 ms
如上所示,我们已经可以通过容器名"mysqld5.7"连接mysql服务器了。
- 断开网络: 由于我们的容器仍然连接着默认bridge
docker0
,而现在我们已经不需要它,所以应该将容器与docker0
的连接断开,执行以下操作:
# 断开容器与docker0的连接
docker network disconnect bridge test_demo
docker network disconnect bridge mysqld5.7
最新评论
# 这只是一个创建远程登录并授权的语句、仅作为记录 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'Fit2cloud!' WITH GRANT OPTION;
当MGR集群初始化结束后,需要开启MGR集群自启动(需要有一台节点是自动开启引导) loose-group_replication_start_on_boot = ON #设置节点是否在启动时自动启动 MGR 集群 loose-group_replication_bootstrap_group = ON #设置节点是否作为初始引导节点启动集群
密码:blog.sirliu.com
本内容密码:blog.sirliu.com 最新整理的文章在这里喔:https://blog.sirliu.com/2018/11/shell_lian_xi_ti.html