“MySQL 不能用 Docker 部署”,这句话在技术社区里流传了很久。我几乎每隔一段时间就能看到有人在讨论组里争论:生产环境 MySQL 到底能不能跑在容器里?一方会搬出“数据放容器里,重启就没了”“性能损耗太大”“网络隔离太复杂”这些理由,另一方则坚持容器化是大势所趋,数据库也不例外。
我的判断是:这个说法一半对一半错。错的地方在于,很多人把“我不会用 Docker 部署 MySQL”当成了“Docker 不适合部署 MySQL”。真正的问题从来不是 Docker 本身,而是三个关键词:数据持久化、网络模式、运维边界。
这篇文章我会先分析这种论调为什么会出现,再带你用 Docker 完整部署一个 MySQL 8.0 实例,包含数据卷挂载、配置文件管理、备份恢复、常见排查和生产环境建议。读完你会发现,用 Docker 部署 MySQL 不是“行不行”的问题,而是“怎么用才不出事”的问题。
1. “MySQL 不能用 Docker 部署”的说法从哪来
1.1 数据持久化焦虑
反对 Docker 部署 MySQL 的第一理由永远是数据。很多人第一次用 Docker 跑 MySQL,容器一停、一删,数据库里的数据也一起消失了。这个体验确实会给人留下心理阴影,于是结论就变成了“MySQL 不适合 Docker”。
但这里真正的原因,是操作者没有理解 Docker 容器的文件系统生命周期。容器默认是无状态的,所有写在容器可写层的数据,都会随着容器删除而消失。正确做法是使用数据卷(Volume)或宿主机目录挂载,把 MySQL 的/var/lib/mysql目录映射到宿主机上。数据一旦持久化到宿主机,容器本身变得“可丢弃”,你删除容器、重建容器、升级镜像,数据都不会丢。
换句话说,问题不在 Docker,而是缺少“容器的思考方式”。
1.2 性能损耗的误解
另外一个常见说法是 Docker 容器有性能损耗,数据库这种 I/O 密集型应用不适合容器化。
早期 Docker 使用 NAT 网络和普通存储驱动时,确实有一些额外开销。但现在主流的 Linux 环境默认使用 OverlayFS 和桥接网络,MySQL 跑在容器里和跑在宿主机上,性能差异已经非常小。真正影响 MySQL 性能的是磁盘类型(SSD 还是机械盘)、CPU 分配、内存大小、MySQL 参数配置,而不是前面多了一层 Docker。
从实际使用看,中小型项目把 MySQL 跑在 Docker 里,性能是完全没有问题的。大型项目真正要考虑的不是“能不能用 Docker”,而是“怎么给容器分配资源、怎么做监控、怎么做高可用”。
1.3 运维复杂度的恐惧
有人说 Docker 部署 MySQL 太复杂,要懂镜像、容器、卷、端口映射、环境变量,比直接apt install mysql-server麻烦多了。
这句话在最初学习时成立,但放到工程环境里就不成立。Docker 部署 MySQL 的真正价值,是把整套环境代码化。你可以用一份docker-compose.yml描述完整实例,团队成员拉下来就能跑出一模一样的数据库环境;你可以快速创建多个隔离实例用于测试;你可以通过更换镜像标签完成版本升级。这些能力在传统安装方式下需要大量人工操作,而且环境差异极大。
所以我在这篇文章开头就说:不能只看“能不能”,还要看“适合谁”。对于本地开发、测试环境、CI/CD、中小型项目,Docker 部署 MySQL 是非常合适的;对于大型高并发生产环境,只要补充监控、备份、资源限制等工程能力,同样可行。
2. Docker 部署 MySQL 的核心概念
在敲命令之前,先花几分钟理解几个基础概念。如果你已经被各种教程绕晕,这里会帮你把关键点理清楚。
2.1 镜像与容器
镜像(Image)是一个只读的模板,MySQL 的镜像中已经打包好了 MySQL 程序、默认配置、运行需要的依赖库。容器(Container)是镜像的运行实例,真正执行时会在镜像之上增加一个可写层。
你可以把镜像理解为“安装包”,容器理解为“安装好并正在运行的程序”。同一个mysql:8.0镜像,可以启动多个容器,每个容器之间相互隔离。
2.2 数据卷与挂载
数据卷是 Docker 管理的一块宿主机存储空间。它独立于容器生命周期,容器删除了,卷里的数据还在。
MySQL 在容器内部把数据写到/var/lib/mysql目录。为了持久化,你需要把这个目录挂载到宿主机目录或数据卷上。命令参数是-v:
-v /data/mysql:/var/lib/mysql这条配置的含义是:容器内写到/var/lib/mysql的数据,实际存放在宿主机/data/mysql目录。只要这个目录在,数据就是安全的。
2.3 端口映射
容器默认使用独立的网络命名空间,宿主机访问不到容器里的 3306 端口。你需要将宿主机的端口映射到容器端口:
-p 3306:3306含义是:宿主机 3306 端口收到的请求,转发到容器的 3306 端口。你本地的 Navicat、MySQL Workbench、应用程序连接127.0.0.1:3306就能到达容器内的 MySQL。
2.4 环境变量
MySQL 官方镜像支持通过环境变量完成初始化操作。比如MYSQL_ROOT_PASSWORD可以指定 root 密码,MYSQL_DATABASE可以在首次启动时自动创建一个数据库。这些是官方镜像提供的便利,使用前最好确认镜像文档,不要凭记忆写。
2.5 重启策略
--restart=always表示容器意外退出或 Docker 服务重启后,容器会自动拉起。对一个数据库实例来说,这个参数在大部分场景下是推荐加上的。
3. 环境准备:Docker 运行环境与镜像下载
3.1 安装 Docker
Windows 和 macOS 用户通常安装 Docker Desktop。安装过程中如果遇到“Docker Desktop failed to start because virtualisation support wasn't detected”这样的提示,基本可以判断是 CPU 虚拟化没有开启。去 BIOS 设置里确认 Intel VT-x 或 AMD-V 是否启用,Windows 用户还可以检查 Hyper-V 和 Windows 虚拟机监控程序平台是否打开。
Linux 用户直接用系统包管理器安装。以 Ubuntu 为例:
sudo apt update sudo apt install docker.io docker-compose-v2 sudo systemctl enable --now docker安装完成后验证:
docker --version docker compose version如果docker compose命令不可用,说明你安装的是旧版 docker-compose,可以使用docker-compose命令验证。
3.2 镜像加速配置
在国内网络环境下,拉取 Docker Hub 官方镜像经常遇到超时或下载缓慢。可以在 Docker 守护进程配置中设置镜像加速器。
Linux 下修改/etc/docker/daemon.json:
{ "registry-mirrors": ["https://your-mirror.example.com"] }注意:这里的镜像加速地址要以你所在网络环境实际可用的为准。Docker Desktop 则可以直接在 Settings -> Docker Engine 中配置。配置完成后重启 Docker,再拉取镜像就会快很多。
3.3 验证 Docker 是否可用
docker run --rm hello-world该命令会拉取一个最小的测试镜像并运行,输出 Hello from Docker 就说明环境正常。--rm表示容器运行结束后自动删除,适合这种临时测试。
4. 快速入门:Docker 部署 MySQL 8.0 最小示例
下面以 MySQL 8.0 为例,演示完整的部署流程。版本可以换成你需要的版本,比如mysql:5.7,但命令和配置思路是一样的。
4.1 准备宿主机目录
mkdir -p /data/mysql/conf mkdir -p /data/mysql/data mkdir -p /data/mysql/logs这三个目录分别用于存放配置文件、数据文件、日志文件。
4.2 启动 MySQL 容器
docker run -d \ --name mysql8 \ -p 3306:3306 \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=Root@123456 \ -e MYSQL_DATABASE=app_db \ -e MYSQL_USER=app_user \ -e MYSQL_PASSWORD=App@123456 \ -v /data/mysql/conf:/etc/mysql/conf.d \ -v /data/mysql/data:/var/lib/mysql \ -v /data/mysql/logs:/var/log/mysql \ --restart=always \ mysql:8.0解释一下各参数的作用:
| 参数 | 作用 |
|---|---|
-d | 后台运行容器 |
--name mysql8 | 容器名称,后续操作都通过这个名字引用 |
-p 3306:3306 | 宿主机 3306 端口映射到容器 3306 端口 |
-e TZ=Asia/Shanghai | 设置容器时区,避免 MySQL 时间与本地相差 8 小时 |
-e MYSQL_ROOT_PASSWORD | 初始化 root 用户密码 |
-e MYSQL_DATABASE | 首次启动时自动创建数据库 |
-e MYSQL_USER/MYSQL_PASSWORD | 创建普通用户并授权该数据库 |
-v | 数据、配置、日志目录挂载到宿主机 |
--restart=always | 容器退出后自动重启 |
这里真正容易踩坑的地方是密码设置。如果密码中包含$、!、&等特殊字符,bash 可能会做特殊解析,建议使用单引号包裹整个参数,或者干脆先用简单密码跑通,再在初始化后修改。
4.3 验证容器状态
docker ps如果STATUS列显示Up或Up X seconds,说明容器正在运行。如果容器反复重启,用下面的命令查看日志:
docker logs mysql84.4 使用容器内命令验证 MySQL
docker exec -it mysql8 mysql -uroot -p输入 root 密码后进入 MySQL 命令行。执行:
SHOW DATABASES; SELECT VERSION();看到app_db存在且版本为 8.x,说明数据库初始化成功。
4.5 从宿主机连接验证
如果你本机安装了 MySQL 客户端:
mysql -h127.0.0.1 -P3306 -uroot -p注意这里要使用127.0.0.1而不是localhost。某些客户端在连接localhost时会尝试走 Unix Socket,而 Socket 在宿主机上并不存在,连接会失败。
如果用 MySQL Workbench,连接参数为:
- Hostname:
127.0.0.1 - Port:
3306 - Username:
root
到这里,一个最基本的 Docker MySQL 已经跑起来了。但实际项目不会只用一条docker run命令,因为参数太多、不好维护,下一节用 docker-compose 做工程化部署。
5. 工程化部署:使用 docker-compose 组织 MySQL
当你需要管理多个容器,或者希望把数据库环境配置写进项目仓库,docker-compose是更合适的选择。
5.1 编写 docker-compose.yml
创建目录并编写文件:
# 文件路径:/data/mysql/docker-compose.yml services: mysql8: image: mysql:8.0 container_name: mysql8 restart: always environment: TZ: Asia/Shanghai MYSQL_ROOT_PASSWORD: Root@123456 MYSQL_DATABASE: app_db MYSQL_USER: app_user MYSQL_PASSWORD: App@123456 ports: - "3306:3306" volumes: - /data/mysql/data:/var/lib/mysql - /data/mysql/conf:/etc/mysql/conf.d - /data/mysql/logs:/var/log/mysql5.2 启动服务
在 docker-compose.yml 所在目录下执行:
docker compose up -d查看状态:
docker compose ps停止服务:
docker compose down注意:docker compose down会停止并删除容器,但不会删除数据卷。因为这里使用的是宿主机目录挂载,数据依然保留在/data/mysql/data。这个命令是安全的,但要清楚它和down -v的区别。docker compose down -v会连带删除匿名卷和命名卷,如果不理解这句话的含义,不要随意加-v。
5.3 编写 MySQL 配置文件
MySQL 官方镜像默认会读取/etc/mysql/conf.d目录下的.cnf文件。我们把自定义配置放在宿主机/data/mysql/conf目录下。
# 文件路径:/data/mysql/conf/my-custom.cnf [mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci default-time-zone=+08:00 max_connections=200保存后重启容器:
docker restart mysql8进入 MySQL 验证配置是否生效:
docker exec -it mysql8 mysql -uroot -pSHOW VARIABLES LIKE 'character_set_server'; SHOW VARIABLES LIKE 'collation_server'; SHOW VARIABLES LIKE 'max_connections';5.4 使用初始化脚本
如果你希望 MySQL 首次启动时自动执行建表或初始化 SQL,可以把.sql脚本放到一个共享目录,并挂载到容器内的/docker-entrypoint-initdb.d。
目录结构:
/data/mysql ├── docker-compose.yml ├── conf │ └── my-custom.cnf ├── data └── init └── 01_init.sql修改 docker-compose.yml,增加一行挂载:
volumes: - /data/mysql/data:/var/lib/mysql - /data/mysql/conf:/etc/mysql/conf.d - /data/mysql/logs:/var/log/mysql - /data/mysql/init:/docker-entrypoint-initdb.d/docker-entrypoint-initdb.d目录下的.sql脚本只在数据目录为空(即首次初始化)时执行。如果你已经启动过容器,再放脚本进去不会触发执行。这是新手容易误解的地方:初始化脚本不是每次启动都跑,而是只在数据库第一次创建时执行。
5.5 后续如何安全修改配置文件
修改my-custom.cnf后,推荐按以下顺序操作:
docker compose down docker compose up -d为什么不用docker restart?因为部分 MySQL 配置项在重启容器时也能加载,但down和up能确保容器以全新配置重新创建,避免某些残留状态影响判断。如果你在测试环境操作,可以放心使用;生产环境修改配置前,先备份、先在低峰期操作、准备回滚步骤。
6. 数据持久化与常用操作
6.1 确认数据确实持久化到了宿主机
启动容器后,查看宿主机数据目录:
ls -l /data/mysql/data你会看到ibdata1、#innodb_temp、数据库目录等文件。这些就是 MySQL 的真实数据文件。测试持久化很简单:
docker exec -it mysql8 mysql -uroot -pCREATE DATABASE persist_test;然后删除容器:
docker rm -f mysql8重新用同样的命令或 docker-compose 启动一个新容器:
docker compose up -d再进入 MySQL 查看:
SHOW DATABASES;persist_test还在。这就证明了数据持久化配置是生效的。很多人第一次验证这个动作后,对 Docker 部署数据库的恐惧会消除一大半。
6.2 常用运维命令
查看容器日志:
docker logs --tail 200 mysql8实时跟踪日志:
docker logs -f mysql8进入容器 bash 环境:
docker exec -it mysql8 bash在容器内执行任意 MySQL 命令:
docker exec mysql8 mysql -uroot -p -e "SHOW PROCESSLIST;"复制文件到宿主机:
docker cp mysql8:/var/lib/mysql/ibdata1 /data/backup/6.3 创建专用业务账号
生产环境不建议所有应用都使用 root 账号。更稳妥的做法是创建最小权限的专用账号:
CREATE USER 'app_only'@'%' IDENTIFIED BY 'App@123456'; GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_only'@'%'; FLUSH PRIVILEGES;@'%'表示允许从任意主机连接。如果只想允许某个应用服务器 IP 连接,可以写成'app_only'@'192.168.1.100',这是更严格的安全边界。
7. 备份与恢复:Docker 环境下的数据安全
7.1 为什么备份是必做题
很多 Docker 部署 MySQL 的失败案例,不是部署时出问题,而是某个深夜数据库误删、磁盘损坏、容器异常,才发现没有备份。用 Docker 部署数据库,备份策略不仅不能少,反而要更明确,因为容器生命周期增加了运维变量。
7.2 在容器内执行 mysqldump 备份
最简单的备份方式:
docker exec mysql8 mysqldump -uroot -p --single-transaction --routines --triggers app_db > /data/backup/app_db_$(date +%F).sql参数说明:
| 参数 | 作用 |
|---|---|
--single-transaction | 使用事务保证备份一致性,避免锁表,适合 InnoDB |
--routines | 备份存储过程和函数 |
--triggers | 备份触发器 |
app_db | 要备份的数据库名 |
执行后,备份文件保存在宿主机/data/backup目录,不受容器生命周期影响。
为了避免密码出现在命令行历史中,也可以让 mysqldump 交互式提示输入密码:
docker exec -it mysql8 mysqldump -uroot -p --single-transaction --routines --triggers app_db > /data/backup/app_db.sql7.3 定时备份脚本
生产环境建议使用 crontab 定时执行备份,并保留最近 N 天的备份文件。
#!/bin/bash # 文件路径:/data/scripts/mysql_backup.sh BACKUP_DIR=/data/backup DATE=$(date +%F_%H%M) docker exec mysql8 mysqldump -uroot -p'Root@123456' --single-transaction --routines --triggers app_db > "$BACKUP_DIR/app_db_$DATE.sql" find "$BACKUP_DIR" -name "app_db_*.sql" -mtime +7 -delete给脚本加执行权限:
chmod +x /data/scripts/mysql_backup.sh添加定时任务:
crontab -e0 3 * * * /data/scripts/mysql_backup.sh每天凌晨 3 点执行备份,并自动清理 7 天前的备份文件。
7.4 恢复数据
恢复前先确认目标库为空,避免数据覆盖冲突:
docker exec -i mysql8 mysql -uroot -p app_db < /data/backup/app_db_2025-01-01.sql如果是误删了一个表,也可以从这个备份文件中提取该表的 INSERT 语句,只恢复指定表,避免全量恢复的风险。
7.5 不能只做备份,还要做恢复演练
备份文件不可读、恢复步骤出错,这比没有备份更糟糕。建议每季度至少做一次恢复演练:在一个临时容器中导入备份文件,验证表结构和数据量是否正常,然后丢弃临时容器。用 Docker 做恢复演练其实非常方便,起一个临时 MySQL 容器,挂载备份目录,导入,检查,再删除,整个过程与线上环境隔离。
8. Docker 部署 MySQL 的常见问题与排查
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
容器一直重启,docker ps状态为 Restarting | 数据目录权限不对、配置错误、磁盘空间不足 | docker logs mysql8查看详细错误 | 检查挂载目录权限,使用chmod或chown调整;检查磁盘空间df -h |
| 宿主机连接 3306 失败 | 端口映射未生效、防火墙拦截、云安全组未放行 | docker port mysql8查看映射;ss -lntp检查端口监听 | 确认-p 3306:3306存在;放行防火墙端口;云服务器检查安全组 |
| 删除容器后数据丢失 | 未挂载数据卷 | 检查启动命令是否包含-v配置 | 把/var/lib/mysql挂载到宿主机目录或命名卷,重新部署 |
Navicat / Workbench 连接报错Authentication plugin 'caching_sha2_password' cannot be loaded | MySQL 8.0 默认认证插件与旧客户端不兼容 | 查看客户端版本 | 创建用户时指定mysql_native_password,或升级客户端工具 |
| 容器内时间比本地晚 8 小时 | 容器时区未设置 | 执行date查看容器时间 | 环境变量增加TZ=Asia/Shanghai,或挂载/etc/localtime |
| 自定义配置文件不生效 | 配置文件未放到/etc/mysql/conf.d,或权限过松 | docker exec mysql8 cat /etc/mysql/my.cnf查看 include 目录 | 确认配置放在/etc/mysql/conf.d下,文件权限为 644 |
docker pull mysql:8.0非常慢 | 网络环境影响镜像下载 | 观察拉取速度和超时信息 | 配置 registry mirror 镜像加速器,或改用内网镜像仓库 |
| Docker Desktop 无法启动,提示检测不到虚拟化支持 | BIOS 未开启硬件虚拟化 | 检查任务管理器中的虚拟化状态 | 重启进入 BIOS,开启 Intel VT-x 或 AMD-V,并启用 Windows Hyper-V |
连接报错Host 'x.x.x.x' is not allowed to connect to this MySQL server | 用户只允许 localhost 连接 | 查看 MySQL 用户表 Host 字段 | 创建'user'@'%'或指定网段账号,并执行FLUSH PRIVILEGES; |
8.1 认证插件问题详解
MySQL 8.0 默认使用caching_sha2_password认证插件,而一些旧版本的客户端、驱动(比如某些 Delphi 组件)只支持mysql_native_password,连接时就会报出类似 “Client does not support authentication protocol requested by server” 的错误。
解决方法有两种:
第一种,在创建用户时指定认证插件:
CREATE USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'App@123456';第二种,修改已有用户的认证插件:
ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'App@123456'; FLUSH PRIVILEGES;推荐优先升级客户端或驱动到支持caching_sha2_password的版本,因为这是 MySQL 8.0 的默认安全策略,长期更安全。如果客户端版本确实无法升级,再使用第二种方案。
8.2 数据目录权限问题
启动 MySQL 容器时,如果宿主机挂载目录权限不正确,容器日志会出现类似这样的错误:
[ERROR] [MY-012574] InnoDB: The redo log file was created before upgrading to 8.0.30 [ERROR] The designated data directory /var/lib/mysql is unusable.排查的第一步是确保挂载目录能够被容器内 mysql 用户读写。最直接的方案是把目录属主改为容器内使用的用户 ID(MySQL 官方镜像中 mysql 用户 UID 通常是 999):
chown -R 999:999 /data/mysql/data chown -R 999:999 /data/mysql/logs不要在生产环境随意使用chmod -R 777,这会造成严重安全隐患。
9. 生产环境最佳实践与选型建议
9.1 必须遵守的六条规则
第一,永远使用固定版本标签。不要用mysql:latest,因为latest会随着镜像更新而变化,你无法确定线上环境跑的是哪个版本。推荐使用mysql:8.0.36这样带小版本的标签,即使要升级,也要在测试环境验证后再改标签。
第二,数据卷与容器生命周期解耦。容器可以被删除、重建、替换,但数据目录必须始终保留在宿主机。每次部署前都要确认挂载路径正确,不要依赖容器内部数据。
第三,配置文件必须显式管理。不要进入容器手改配置,因为容器重建后修改会丢失。所有配置写入宿主机挂载目录,并通过 docker-compose 文件管理。
第四,密码不要硬编码在启动命令中。命令行中的环境变量会被进程列表看到。更稳妥的方式是使用.env文件配合 docker-compose,并确保.env文件的权限为 600。
MYSQL_ROOT_PASSWORD=Root@123456 MYSQL_DATABASE=app_db MYSQL_USER=app_user MYSQL_PASSWORD=App@123456docker-compose.yml 中可以这样引用:
environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD}第五,健康检查要配上。在 docker-compose.yml 中增加健康检查,可以知道 MySQL 是否真正可用,而不是只看容器有没有在运行。
healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"] interval: 10s timeout: 5s retries: 5第六,日志要限制大小。MySQL 容器如果一直不清理日志,日志文件可能占满磁盘。建议在容器启动参数中限制日志大小:
docker run -d \ --log-opt max-size=100m \ --log-opt max-file=3 \ ...9.2 什么时候不要用 Docker 部署 MySQL
再回到开头的问题。Docker 部署 MySQL 确实不是所有场景的最优解。
如果你的项目属于以下情况,可以优先考虑物理机或云厂商的托管数据库:
第一,超大规模、超高并发场景。当单实例承载的核心业务流量非常大,对磁盘 I/O、网络延迟、内核参数都有极致要求时,使用物理机部署 MySQL 并做深度调优,会让你少很多解释成本。
第二,已有强运维规范和大规模数据库集群。如果团队已经有成熟的 MySQL 运维平台、监控系统、备份恢复体系,强行容器化反而增加了适配成本,除非平台本身已经支持容器化 MySQL。
第三,对合规和审计要求极高的场景。有些业务为了满足等保、审计等要求,需要精确到进程级别的安全管控,传统部署方式更容易满足这类要求。
但是,以下场景我非常推荐使用 Docker:
- 本地开发环境,用 Docker 快速拉起一个与生产版本一致的 MySQL,而不是在本机装一堆依赖。
- 测试环境,特别是 CI/CD 中需要临时数据库跑测试用例的场景,用完即删,干净利落。
- 团队协作时,通过 docker-compose 文件保证所有开发人员数据库环境一致,避免“在我电脑上是好的”这类问题。
- 中小型项目,Docker 部署 MySQL 配合定时备份和监控,成本远低于维护一台专门数据库服务器。
9.3 从“能不能”到“怎么用”
如果你在犹豫要不要用 Docker 部署 MySQL,我建议先做一个实验:在测试环境用 Docker 部署一个 MySQL 8.0,挂载数据卷,跑 7 天,然后故意删除容器再重建,验证数据是否还在。这个实验没有风险,却能让你对容器、卷、镜像的关系形成最直观的理解。
有了这层理解,你再看网上那些“MySQL 不能用 Docker 部署”的声音,会发现它们大多不是在说 Docker 不行,而是在说“我没掌握数据持久化方法”或“我遇到性能问题时没有排查手段”。
技术选型从来不是非黑即白。Docker 部署 MySQL 适合的场景非常明确:开发、测试、中小规模生产、追求环境一致性。它不适合的场景也很明确:超大规模高并发、已有复杂运维体系、强合规环境。清楚这些边界,比争论“行不行”重要得多。
如果你想继续深入,下一步可以研究 Docker 网络模式,比如用桥接网络让 MySQL 容器和应用容器通过容器名称互通;也可以研究如何在 Docker 里做主从复制,两个 MySQL 容器配合实现读写分离;或者研究 Docker 镜像的构建和版本管理,把 MySQL 初始化脚本和配置打成自定义镜像。
下次再有人反复强调“MySQL 不能用 Docker 部署”,你可以心平气和地问一句:你的数据卷挂在哪了?大概率听到的回答会是沉默。