Docker上的MySQL:MySQL容器的单主机网络

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本文讲的是Docker上的MySQL:MySQL容器的单主机网络【编者的话】网络是Docker至关重要的一部分,本文以MySQL容器为例,详细介绍了Docker所支持的各种网络,值得一读。
本文讲的是Docker上的MySQL:MySQL容器的单主机网络【编者的话】网络是Docker至关重要的一部分,本文以MySQL容器为例,详细介绍了Docker所支持的各种网络,值得一读。

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

在之前的两篇博文里,我介绍了 在容器里运行MySQL的基础 如何构建自定义的MySQL镜像 。这篇博文里,将继续介绍Docker是如何处理单主机网络的,以及MySQL容器如何利用这个功能。

3种类型网络

默认来说,Docker安装时在宿主机上创建了3个网络:
$ docker network ls
NETWORK ID          NAME                DRIVER
1a54de857c50        host                host
1421a175401a        bridge              bridge
62bf0f8a1267        none                null

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

Host网络

host网络将容器添加到宿主机的网络堆栈上。你可以认为容器所运行的网络连接到了和宿主机相同的网络接口上。它的特征如下:
  • 容器的网络接口和宿主机是完全相同的。
  • 每个宿主机仅有一个host网络。无法创建更多的。
  • 必须在“docker run”命令行里显式指定"--net=host",给容器分配该网络。
  • 容器链接,不支持 “--link mysql-container:mysql”
  • 端口映射,不支持 “-p 3307:3306”

让我们使用“--net=host”在宿主网络上创建一个容器:
$ docker run \
--name=mysql-host \
--net=host \
-e MYSQL_ROOT_PASSWORD=mypassword \
-v /storage/mysql-host/datadir:/var/lib/mysql \
-d mysql

查看容器网络接口,可以看到容器内的网络配置和宿主机是完全一样的:
[machine-host]$ docker exec -it mysql-host /bin/bash
[container-host]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
   valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
   valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:fa:f6:30 brd ff:ff:ff:ff:ff:ff
inet 192.168.55.166/24 brd 192.168.55.255 scope global eth0
   valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fefa:f630/64 scope link
   valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:93:50:ee:c8 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
   valid_lft forever preferred_lft forever
inet6 fe80::42:93ff:fe50:eec8/64 scope link

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

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

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

在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 run \
--name=mysql-bridge \
-p 3307:3306 \
-e MYSQL_ROOT_PASSWORD=mypassword \
-v /storage/mysql-bridge/datadir:/var/lib/mysql \
-d mysql

查看容器的网络接口,可以看到Docker创建了一个网络接口,eth0(不包含localhost):
[machine-host]$ docker exec -it mysql-container-bridge /bin/bash
[container-host]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
   valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
   valid_lft forever preferred_lft forever
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
   valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
   valid_lft forever preferred_lft forever

默认来说,Docker利用iptables来管理转发到bridge网络的包。每个出站的连接看上去都是从宿主机自己的IP地址之一发送出去的。如下是上述容器启动后机器的NAT chain:
[machine-host]$ iptables -L -n -t nat
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           tcp dpt:3306

Chain DOCKER (2 references)
target     prot opt source               destination
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:3307 to:172.17.0.2:3306

上述规则,基于“docker run” 命令行里指定的端口映射参数 “-p 3307:3306”,允许3307端口暴露在宿主机上。查看宿主机的netstat输出,可以看到MySQL在端口3307上侦听,属于docker-proxy进程:
[machine-host]$ netstat -tulpn | grep 3307
tcp6       0      0 :::3307                 :::*                    LISTEN      4150/docker-proxy

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

默认的bridge网络支持端口映射和容器链接的使用,允许docker0网络上的容器间的通信。关于如何通过暴露环境变量链接容器,以及如何通过/etc/hosts文件自动配置主机映射, Docker文档 提供了详尽的信息。
用户定义的bridge
Docker让用户可以创建自定义的bridge网络,也就是用户定义的bridge网络(也可以创建用户定义的overlay网络,但是我们计划在下一篇博文里讨论这一点)。它的行为和docker0网络一样,网络里的每个容器能够立即和网络里的其他容器通信。但是,网络本身将容器和外部网络隔离开了。

该网络方式的最大的好处在于,所有容器都能够解析容器名。考虑如下网络:
[machine-host]$ docker network create mysql-network

然后,在用户定义网络里创建5个MySQL容器:
[machine-host]$ for i in {1..5}; do docker run --name=mysql$i --net=mysql-network -e MYSQL_ROOT_PASSWORD=mypassword -d mysql; done

现在,登录进其中一个容器(mysql3):
[machine-host]$ docker exec -it mysql3 /bin/bash

我们随后可以ping通该网络里的所有容器,而完全不需要链接它们:
[mysql3-container]$ for i in {1..5}; do ping -c 1 mysql$i ; done
PING mysql1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.151 ms
--- mysql1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.151/0.151/0.151/0.000 ms
PING mysql2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: icmp_seq=0 ttl=64 time=0.138 ms
--- mysql2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.138/0.138/0.138/0.000 ms
PING mysql3 (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: icmp_seq=0 ttl=64 time=0.087 ms
--- mysql3 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.087/0.087/0.087/0.000 ms
PING mysql4 (172.18.0.5): 56 data bytes
64 bytes from 172.18.0.5: icmp_seq=0 ttl=64 time=0.353 ms
--- mysql4 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.353/0.353/0.353/0.000 ms
PING mysql5 (172.18.0.6): 56 data bytes
64 bytes from 172.18.0.6: icmp_seq=0 ttl=64 time=0.135 ms
--- mysql5 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.135/0.135/0.135/0.000 ms

如果查看resolver的设置,可以看到Docker配置为一个内嵌的DNS服务器:
[mysql3-container]$ cat /etc/resolv.conf
search localdomain
nameserver 127.0.0.11
options ndots:0

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

默认 vs. 用户定义Bridge
下表展示了这两种网络的主要不同点:
picture.jpg

No网络

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

通过查看容器的网络接口,仅仅localhost的接口是可用的:
[machine-host]$ docker exec -it mysql0 /bin/bash
[mysql0-container]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
   valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
   valid_lft forever preferred_lft forever

在network none里的容器意味着它无法加入任何网络。虽然如此,MySQL容器仍然在运行,用户可以从shell里通过localhost或者socket使用mysql客户端命令行直接访问该实例:
[mysql0-container]$ mysql -uroot -pmypassword -h127.0.0.1 -P3306
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.13 MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

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

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

本片博文至此完结。下一篇博文里,会继续研究和Docker Swarm一起使用的多主机网络(使用overlay网络),Docker Swarm是管理多台宿主机上容器的编排工具。

原文链接:MySQL on Docker: Single Host Networking for MySQL Containers(翻译:崔婧雯 校对:)  
===========================
译者介绍

崔婧雯,现就职于IBM,高级软件工程师,负责IBM WebSphere业务流程管理软件的系统测试工作。曾就职于VMware从事桌面虚拟化产品的质量保证工作。对虚拟化,中间件技术,业务流程管理有浓厚的兴趣。

原文发布时间为:2016-08-05

本文作者:崔婧雯

本文来自云栖社区合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。

原文标题:Docker上的MySQL:MySQL容器的单主机网络

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5天前
|
存储 运维 监控
构建高效稳定的Docker容器监控体系
【4月更文挑战第18天】 在现代微服务架构中,Docker容器已成为部署和运行应用的标准环境。随之而来的挑战是如何有效监控这些容器的性能与健康状况,确保系统的稳定性和可靠性。本文将探讨构建一个高效稳定的Docker容器监控体系的关键技术和方法,包括日志管理、性能指标收集以及异常检测机制,旨在为运维人员提供实用的指导和建议。
11 0
|
12天前
|
关系型数据库 MySQL 数据库
Docker安装MySQL
Docker安装MySQL
23 1
|
14天前
|
Linux Docker 容器
docker 容器常用命令
docker 容器常用命令
13 0
|
14天前
|
关系型数据库 MySQL 数据库
docker自定义安装mysql 5.7
docker自定义安装mysql 5.7
22 0
|
14天前
|
Linux Shell 虚拟化
linux 部署docker容器虚拟化平台(二)--------docker 镜像制作方法
linux 部署docker容器虚拟化平台(二)--------docker 镜像制作方法
25 0
|
14天前
|
存储 Linux Shell
centos 部署docker容器 安装 、基本使用方法(一)
centos 部署docker容器 安装 、基本使用方法(一)
26 0
|
23天前
|
Kubernetes 网络协议 Docker
Docker 容器的DNS
Docker 容器的DNS
28 1
|
25天前
|
关系型数据库 MySQL Nacos
【深入浅出Nacos原理及调优】「实战开发专题」采用Docker容器进行部署和搭建Nacos服务以及“坑点”
【深入浅出Nacos原理及调优】「实战开发专题」采用Docker容器进行部署和搭建Nacos服务以及“坑点”
46 1
|
1月前
|
Java Go 开发者
Docker容器技术简介及其与Go语言的结合点
【2月更文挑战第23天】本文首先概述了Docker容器技术的核心概念和优势,接着探讨了Go语言与Docker容器技术的结合点。通过阐述Docker的轻量级、可移植性和版本控制等特性,以及Go语言在容器化应用中的优势,本文旨在说明两者结合能够实现更高效、灵活的应用开发和部署。
|
1月前
|
Oracle 关系型数据库 数据库