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
目录
打赏
0
0
0
0
74
分享
相关文章
docker拉取MySQL后数据库连接失败解决方案
通过以上方法,可以解决Docker中拉取MySQL镜像后数据库连接失败的常见问题。关键步骤包括确保容器正确启动、配置正确的环境变量、合理设置网络和权限,以及检查主机防火墙设置等。通过逐步排查,可以快速定位并解决连接问题,确保MySQL服务的正常使用。
95 82
zabbix7.0.9安装-以宝塔安装形式-非docker容器安装方法-系统采用AlmaLinux9系统-最佳匹配操作系统提供稳定运行环境-安装教程完整版本-优雅草卓伊凡
zabbix7.0.9安装-以宝塔安装形式-非docker容器安装方法-系统采用AlmaLinux9系统-最佳匹配操作系统提供稳定运行环境-安装教程完整版本-优雅草卓伊凡
59 30
自学软硬件第755 docker容器虚拟化技术youtube视频下载工具
docker容器虚拟化技术有什么用?怎么使用?TubeTube 项目使用youtube视频下载工具
美团面试:MySQL为什么 不用 Docker部署?
45岁老架构师尼恩在读者交流群中分享了关于“MySQL为什么不推荐使用Docker部署”的深入分析。通过系统化的梳理,尼恩帮助读者理解为何大型MySQL数据库通常不使用Docker部署,主要涉及性能、管理复杂度和稳定性等方面的考量。文章详细解释了有状态容器的特点、Docker的资源隔离问题以及磁盘IO性能损耗,并提供了小型MySQL使用Docker的最佳实践。此外,尼恩还介绍了Share Nothing架构的优势及其应用场景,强调了配置管理和数据持久化的挑战。最后,尼恩建议读者参考《尼恩Java面试宝典PDF》以提升技术能力,更好地应对面试中的难题。
Docker Compose V2 安装常用数据库MySQL+Mongo
以上内容涵盖了使用 Docker Compose 安装和管理 MySQL 和 MongoDB 的详细步骤,希望对您有所帮助。
184 42
Docker下Mysql8数据备份与恢复
通过以上步骤,您可以在Docker环境下高效地备份和恢复MySQL 8数据库。备份数据时,使用 `mysqldump`工具生成逻辑备份文件,并存储到指定目录;恢复数据时,使用 `mysql`工具从备份文件中读取数据并恢复到数据库。自动化脚本和定时任务的配置可以进一步简化备份和恢复的管理过程。
148 41
课时5:阿里云容器服务:最原生的集成Docker和云服务
阿里云容器服务以服务化形式构建容器基础设施,大幅提升开发效率,简化应用部署流程。通过Docker容器和DevOps工具(如Jenkins),实现自动化部署与迭代,优化企业内部复杂部署问题。该服务支持GPU调度、混合云架构无缝迁移,并与阿里云产品体系无缝集成,提供安全防护、网络负载均衡等多重功能支持。凭借微服务架构,帮助企业突破业务瓶颈,提高资源利用率,轻松应对海量流量。
课时5:阿里云容器服务:最原生的集成Docker和云服务
ubuntu22 编译安装docker,和docker容器方式安装 deepseek
本脚本适用于Ubuntu 22.04,主要功能包括编译安装Docker和安装DeepSeek模型。首先通过Apt源配置安装Docker,确保网络稳定(建议使用VPN)。接着下载并配置Docker二进制文件,创建Docker用户组并设置守护进程。随后拉取Debian 12镜像,安装系统必备工具,配置Ollama模型管理器,并最终部署和运行DeepSeek模型,提供API接口进行交互测试。
378 15
docker pull mysql:8.0.26提示Error response from daemon: Get “https://registry-1.docker.io/v2/“: EOF错误
docker pull mysql:8.0.26提示Error response from daemon: Get “https://registry-1.docker.io/v2/“: EOF错误
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等