用 Docker 运行 MySQL 测试实例最省事干净,需显式指定 MYSQL_ROOT_PASSWORD,挂载配置文件和数据目录以避免版本差异与数据丢失,并注意初始化脚本仅在空数据目录时执行。

用 Docker 快速起一个隔离的 MySQL 测试实例
最省事、最干净的方式就是用 docker run 启一个官方镜像。它不污染宿主机,启动秒级,数据目录可挂载、端口可映射,适合单机开发和 CI 测试。
- 默认 root 密码必须显式指定,否则容器会启动失败(错误信息:
MYSQL_ROOT_PASSWORD variable is not set) - 建议挂载自定义配置文件,比如通过
-v ./my.cnf:/etc/mysql/conf.d/my.cnf覆盖默认配置,避免因版本差异导致sql_mode或时区行为不一致 - 如果需要保留数据,务必挂载
/var/lib/mysql到宿主机目录;不挂载的话,容器删掉数据就彻底丢了 - 示例命令:
docker run --name mysql-test -d \ -p 3307:3306 \ -e MYSQL_ROOT_PASSWORD=test123 \ -v $(pwd)/data:/var/lib/mysql \ -v $(pwd)/my.cnf:/etc/mysql/conf.d/my.cnf \ -d mysql:8.0
本地编译或包管理器安装时的关键配置项
Mac 用 brew install mysql、Ubuntu 用 apt install mysql-server 虽然方便,但容易和系统已有服务冲突,且默认配置常不适用于测试场景(比如 bind-address=127.0.0.1 不开远程、skip-networking 开着、或默认启用 validate_password 插件)。
- 检查是否监听了正确地址:
netstat -tuln | grep :3306;若只显示127.0.0.1:3306,外部容器或本机其他用户连不上 - 关闭密码强度校验(测试环境不需要):
SET GLOBAL validate_password.policy = LOW;,或在my.cnf中加validate_password_policy=LOW - MySQL 8.0 默认认证插件是
caching_sha2_password,老客户端(如某些 Python MySQLdb 驱动)连不上,可在配置中强制回退:default_authentication_plugin=mysql_native_password
初始化测试库与用户权限要避开的坑
别直接用 root 做应用连接用户——不是安全洁癖,而是权限过大反而掩盖问题(比如误删系统表、没意识到某条语句需要 FILE 权限)。
- 建库前先确认字符集:
CREATE DATABASE test_db CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;,MySQL 8.0 默认排序规则变了,utf8mb4_general_ci已弃用 - 授权时别漏
GRANT ALL ON test_db.* TO 'testuser'@'%';后忘记FLUSH PRIVILEGES;,否则权限不生效 - 如果用 Docker Compose 启多个服务(比如 app + db),
host写成localhost会让应用走 socket 连接,而容器内通常没这个文件;应统一用mysql-test(服务名)或host.docker.internal(Mac/Win)
自动化初始化 SQL 的执行时机很关键
Docker 官方镜像支持在首次启动时自动执行 /docker-entrypoint-initdb.d/ 下的 .sql 或 .sh 文件,但仅对空数据目录生效——也就是说,只要挂载了非空 /var/lib/mysql,这些脚本就完全不会运行。
- 常见误操作:改完初始化 SQL 后反复
docker restart,结果发现表始终没创建——因为数据目录已存在,init 脚本被跳过 - 解决办法只有两个:
docker rm -v mysql-test彻底删容器+卷,或手动进容器执行mysql -uroot -ptest123 - 如果 SQL 里含
CREATE USER,注意 MySQL 8.0 要求必须带IDENTIFIED WITH mysql_native_password BY 'xxx',否则报错Unknown authentication plugin: caching_sha2_password
测试环境的核心不是“能跑”,而是“行为可控”。端口、字符集、认证方式、初始化逻辑这四点一旦不明确,后面 debug 花的时间远超搭环境本身。










