Docker上的MySQL

对于MySQL而言,网络很重要,这是客户端应用程序和其他副本能够成功访问服务器所依赖的基础资源。容器化的MySQL服务的行为由运行“docker run”命令的时候如何生成MySQL镜像来决定。使用Docker单主机网络,MySQL容器可以运行在隔离的环境里(仅仅可以被在相同网络里的容器访问),或者运行在开放环境里(这时MySQL服务完全暴露给外部),或者MySQL实例只是运行着但是没有任何网络。

在这篇博文里,将介绍Docker是如何处理单主机网络的,以及MySQL容器如何利用这个功能。

3种类型网络

默认来说,Docker安装时在宿主机上创建了3个网络:

每个网络的驱动都有自己的特征,下面将详细讨论。

Host网络

host网络将容器添加到宿主机的网络堆栈上。你可以认为容器所运行的网络连接到了和宿主机相同的网络接口上。它的特征如下:

  • 容器的网络接口和宿主机是完全相同的。
  • 每个宿主机仅有一个host网络。无法创建更多的。
  • 必须在“docker run”命令行里显式指定”–net=host”,给容器分配该网络。
  • 容器链接,不支持 “–link mysql-container:mysql”
  • 端口映射,不支持 “-p 3307:3306”

让我们使用“–net=host”在宿主网络上创建一个容器:

查看容器网络接口,可以看到容器内的网络配置和宿主机是完全一样的:

这么设置时,容器不需要在iptables里添加任何转发规则,因为它已经attach到了和宿主一样的网络上。所以,不支持使用参数“-p”的端口映射,并且Docker不会管理运行在这种类型网络上的容器的防火墙规则。
查看宿主机的侦听端口,可以看到3306端口正在侦听:

在Docker宿主网络上运行MySQL容器类似于在宿主机上安装了一个标准的MySQL服务器。这仅仅在你希望将这台宿主机作为独占的MySQL服务器,同时由Docker管理的时候才有用。

这里,容器架构如下图所示:

在host网络上创建的容器能够访问在默认docker0以及用户定义的bridge网络上的容器。

Bridge网络

桥接网络允许多个网络独立通信,同时保证同一台物理宿主机上网络之间的隔离。你可以认为这类似于宿主机内的另一种内部网络。仅仅那些处在相同网络里的容器才能够互相访问,并且能够访问宿主机。如果宿主机能够访问外界,那么容器也就可以。
有两种类型的bridge网络:

  1. 默认bridge(docker0)
  2. 用户定义的bridge
默认bridge(docker0)

默认的bridge网络,docker0在Docker安装的时候会自动创建出来。可以使用“ifconfig”或者“ip a”命令来验证这一点。默认的IP范围是172.17.0.1/16,可以在/etc/default/docker (Debian) 或者/etc/sysconfig/docker (RedHat)里改变该值。如何更改参考Docker文档。

直接开始示例。如果不在“docker run”命令里显式指定“-net”参数,Docker会在默认的docker0网络下创建容器:

查看容器的网络接口,可以看到Docker创建了一个网络接口,eth0(不包含localhost):

默认来说,Docker利用iptables来管理转发到bridge网络的包。每个出站的连接看上去都是从宿主机自己的IP地址之一发送出去的。如下是上述容器启动后机器的NAT chain:

上述规则,基于“docker run” 命令行里指定的端口映射参数 “-p 3307:3306”,允许3307端口暴露在宿主机上。查看宿主机的netstat输出,可以看到MySQL在端口3307上侦听,属于docker-proxy进程:

这种情况下,容器搭建如下图所示:

默认的bridge网络支持端口映射和容器链接的使用,允许docker0网络上的容器间的通信。关于如何通过暴露环境变量链接容器,以及如何通过/etc/hosts文件自动配置主机映射,Docker文档提供了详尽的信息。

用户定义的bridge

Docker让用户可以创建自定义的bridge网络,也就是用户定义的bridge网络(也可以创建用户定义的overlay网络,但是我们计划在下一篇博文里讨论这一点)。它的行为和docker0网络一样,网络里的每个容器能够立即和网络里的其他容器通信。但是,网络本身将容器和外部网络隔离开了。

该网络方式的最大的好处在于,所有容器都能够解析容器名。考虑如下网络:

然后,在用户定义网络里创建5个MySQL容器:

现在,登录进其中一个容器(mysql3):

我们随后可以ping通该网络里的所有容器,而完全不需要链接它们:

如果查看resolver的设置,可以看到Docker配置为一个内嵌的DNS服务器:

内嵌的DNS服务器在容器连接到的网络上,这里是mysql-network时,维护容器名称和其IP地址的映射。该功能辅助网络里的节点发现,在使用MySQL集群技术,比如MySQL复制,Galera Cluster或者MySQL Cluster,构建MySQL容器集群的时候非常有用。

这里,容器搭建如下图所示:

默认 vs. 用户定义Bridge

下表展示了这两种网络的主要不同点:

No网络

我们还可以通过在“docker run”命令里指定“–net=none”创建出没有任何网络的容器。只能通过交互式shell才能访问这样的容器。该节点上不会配置任何额外的网络接口。
如下命令:

通过查看容器的网络接口,仅仅localhost的接口是可用的:

在network none里的容器意味着它无法加入任何网络。虽然如此,MySQL容器仍然在运行,用户可以从shell里通过localhost或者socket使用mysql客户端命令行直接访问该实例:

在该网络上运行的实例的用例是验证MySQL的备份,通过测试恢复流程,准备通过使用,比如Percona Xtrabackup,所创建备份,或者在不同版本的MySQL服务器上测试查询语句。

这里,容器搭建如下图所示:

推荐文章

沪公网安备 31010702002009号