MySQL 8.0 官方镜像不读取 /etc/mysql/my.cnf,仅自动加载 /etc/mysql/conf.d/ 和 /etc/mysql/mysql.conf.d/ 下以 .cnf 结尾的文件;挂载必须用 -v /host/conf:/etc/mysql/conf.d,文件需含 [mysqld] 段、权限为 644、属主 UID 999。

直接挂载到 /etc/mysql/conf.d/ 才生效,挂载到 /etc/mysql/my.cnf 会被忽略 —— 这是绝大多数人启动失败的根源。
为什么 /etc/mysql/my.cnf 挂载不生效?
官方 MySQL 镜像(mysql:8.0、mysql:5.7)**根本不读取顶层 /etc/mysql/my.cnf**,只自动加载 /etc/mysql/conf.d/ 和 /etc/mysql/mysql.conf.d/ 下所有以 .cnf 结尾的文件。即使你用 -v ./my.cnf:/etc/mysql/my.cnf 挂载成功,mysqld 启动时也完全无视它。
常见错误现象:
- 容器反复重启,
docker logs显示卡在getaddrinfo failed或长时间无输出 - 修改了
character-set-server,但SHOW VARIABLES LIKE 'character_set_server'仍是utf8mb3 - 配置里写了
max_connections=1000,实际仍是默认的 151
正确挂载路径和文件名怎么写?
必须把自定义配置文件挂载进 /etc/mysql/conf.d/ 目录,并确保文件名以 .cnf 结尾(如 my.cnf、custom.cnf),且内容以 [mysqld] 开头。
实操建议:
- 宿主机创建配置文件:
mkdir -p /docker/mysql/conf && touch /docker/mysql/conf/custom.cnf - 挂载命令必须用:
-v /docker/mysql/conf/custom.cnf:/etc/mysql/conf.d/custom.cnf:ro(:ro防止容器内误改) - 不要用
--mount type=bind,src=...,dst=/etc/mysql/my.cnf—— 这个路径无效 - 如果宿主机配置目录下有多个
.cnf文件,它们会按字母顺序合并加载,注意避免参数冲突
[mysqld] 段里哪些配置项不能少?
缺了以下两项,容器大概率启动卡死或超时退出:
-
skip-host-cache:禁用主机名缓存,避免 DNS 查询阻塞 -
skip-name-resolve:跳过反向 DNS 解析,否则每次连接都可能触发getaddrinfo调用
其他推荐必配项(尤其生产环境):
-
character-set-server = utf8mb4和collation-server = utf8mb4_unicode_ci(MySQL 8.0 推荐用utf8mb4_0900_ai_ci) -
default-authentication-plugin = mysql_native_password(否则客户端如 Navicat、旧版 JDBC 会连不上) -
secure-file-priv = /var/lib/mysql-files(若需LOAD DATA INFILE,必须显式设值,不能留空或NULL)
改完配置后怎么确认生效?
挂载更新后,必须执行 docker restart <container_name> —— mysqld 不支持热重载,mysqladmin reload 或发 SIGHUP 全无效。
验证方式:
- 进容器查变量:
docker exec -it mysql8 mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "SHOW VARIABLES LIKE 'character_set_server';" - 检查是否跳过 DNS:
docker exec -it mysql8 mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT @@skip_name_resolve;"应返回ON - 看日志有没有报错:
docker logs mysql8 2>&1 | grep -i "unknown variable\|syntax error"
最容易被忽略的是:容器首次初始化后,/var/lib/mysql 已非空,此时改配置不会影响已有表的字符集;只有新建库/表才会用新配置。如果需要全局生效,得从备份还原或手动 ALTER DATABASE。


















