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容器的单主机网络

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
14天前
|
人工智能 弹性计算 运维
ACK Edge与IDC:高效容器网络通信新突破
本文介绍如何基于ACK Edge以及高效的容器网络插件管理IDC进行容器化。
|
10天前
|
NoSQL 关系型数据库 MySQL
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
109 56
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
|
17天前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
156 77
|
25天前
|
监控 Docker 容器
在Docker容器中运行打包好的应用程序
在Docker容器中运行打包好的应用程序
|
3天前
|
存储 Kubernetes 开发者
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
Docker 是一种开源的应用容器引擎,允许开发者将应用程序及其依赖打包成可移植的镜像,并在任何支持 Docker 的平台上运行。其核心概念包括镜像、容器和仓库。镜像是只读的文件系统,容器是镜像的运行实例,仓库用于存储和分发镜像。Kubernetes(k8s)则是容器集群管理系统,提供自动化部署、扩展和维护等功能,支持服务发现、负载均衡、自动伸缩等特性。两者结合使用,可以实现高效的容器化应用管理和运维。Docker 主要用于单主机上的容器管理,而 Kubernetes 则专注于跨多主机的容器编排与调度。尽管 k8s 逐渐减少了对 Docker 作为容器运行时的支持,但 Doc
28 5
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
|
9天前
|
关系型数据库 应用服务中间件 PHP
实战~如何组织一个多容器项目docker-compose
本文介绍了如何使用Docker搭建Nginx、PHP和MySQL的环境。首先启动Nginx容器并查看IP地址,接着启动Alpine容器并安装curl测试连通性。通过`--link`方式或`docker-compose`配置文件实现服务间的通信。最后展示了Nginx配置文件和PHP代码示例,验证了各服务的正常运行。
29 3
实战~如何组织一个多容器项目docker-compose
|
8天前
|
关系型数据库 MySQL 数据库
docker高级篇(大厂进阶):安装mysql主从复制
docker高级篇(大厂进阶):安装mysql主从复制
66 24
|
3天前
|
Unix Linux Docker
CentOS停更沉寂,RHEL巨变限制源代:Docker容器化技术的兴起助力操作系统新格局
操作系统是计算机系统的核心软件,管理和控制硬件与软件资源,为用户和应用程序提供高效、安全的运行环境。Linux作为开源、跨平台的操作系统,具有高度可定制性、稳定性和安全性,广泛应用于服务器、云计算、物联网等领域。其发展得益于庞大的社区支持,多种发行版如Ubuntu、Debian、Fedora等满足不同需求。
16 4
|
18天前
|
数据建模 应用服务中间件 nginx
docker替换宿主与容器的映射端口和文件路径
通过正确配置 Docker 的端口和文件路径映射,可以有效地管理容器化应用程序,确保其高效运行和数据持久性。在生产环境中,动态替换映射配置有助于灵活应对各种需求变化。以上方法和步骤提供了一种可靠且易于操作的方案,帮助您轻松管理 Docker 容器的端口和路径映射。
60 3
|
22天前
|
安全 Docker 容器
docker的默认网络模式有哪些
Docker 默认网络模式包括:1) bridge:默认模式,各容器分配独立IP,可通过名称或IP通信;2) host:容器与宿主机共享网络命名空间,性能最优但有安全风险;3) none:容器隔离无网络配置,适用于仅需本地通信的场景。
35 6