根本原因是配置文件未持久化挂载,Docker重启时从镜像只读层重新加载默认my.cnf;手动编辑或docker cp修改仅存于临时可写层,容器重建后即丢失。

MySQL容器重启后配置还原,根本原因不是MySQL本身“恢复出厂”,而是你改的配置文件没持久化——Docker每次重启都从镜像重新加载只读层,/etc/mysql/my.cnf这类文件一旦没挂载或没重建,就会回到镜像初始状态。
为什么改了my.cnf重启就失效?
Docker容器的文件系统默认是分层只读的。你用docker exec -it mysql-container bash进去手动编辑/etc/mysql/my.cnf,修改只存在于当前容器运行时层;一旦docker restart或docker rm & run,新容器直接从镜像拉起,自然回退到原始配置。
- 镜像里的
my.cnf是静态打包的,不随容器生命周期变化 -
docker cp覆盖配置文件后不重启MySQL服务,MySQL进程仍读旧内存配置 - 即使重启容器,只要没把配置文件挂载出来,改动就白改
正确挂载自定义my.cnf的两种方式
必须让容器启动时就读你自己的配置,而不是进容器再改。
- 用
-v挂载单个配置文件:docker run -v /host/path/my.cnf:/etc/mysql/my.cnf:ro(注意加:ro防止MySQL写崩配置) - 挂载整个
conf.d目录更稳妥(官方镜像支持):-v /host/conf.d:/etc/mysql/conf.d:ro,然后把你的custom.cnf放进去,MySQL会自动加载 - 如果用
docker-compose.yml,写成:volumes: - ./my.cnf:/etc/mysql/my.cnf:ro
docker exec mysql-container mysql连不上?检查端口和socket
配置改错常导致MySQL启动失败,表现为docker ps里容器状态是Restarting或Exited,这时docker logs mysql-container通常会报类似mysqld: Can't read from file '/etc/mysql/my.cnf'或unknown variable 'xxx'。
- 确认
my.cnf语法合法:用mysqld --verbose --help | grep "Default options"查默认配置路径,再用mysqld --defaults-file=/etc/mysql/my.cnf --validate-config验证(需进容器执行) - 避免混用
!includedir和绝对路径,官方镜像默认!includedir /etc/mysql/conf.d/,优先往conf.d/里扔.cnf片段 - 改完配置必须重启容器(不是
mysqladmin shutdown),否则新配置不生效
别依赖/docker-entrypoint-initdb.d/改运行时配置
这个目录只在首次初始化空数据目录时执行SQL或shell脚本,对my.cnf无效。有人把echo "innodb_buffer_pool_size=512M" >> /etc/mysql/my.cnf写进init.sql,结果发现重启后消失——因为init脚本是在容器第一次启动、/var/lib/mysql为空时才跑,之后永远不触发。
-
/docker-entrypoint-initdb.d/适合建库、授权、导入初始数据,不适合改MySQL服务参数 - 真正要调
max_connections、character-set-server这些,必须走挂载配置文件 - 如果要用脚本动态生成配置,得在
ENTRYPOINT里做(复杂且易出错,不推荐)
最常被忽略的是:挂载配置后没检查MySQL是否真用了它——进容器执行mysql -uroot -p -e "SHOW VARIABLES LIKE 'character_set%';",对比my.cnf里设的值,才能确认挂载和解析都没问题。


















