docker-compose.yml 配置需明确指定 mysql:8.0.33 版本、挂载 /var/lib/mysql 并设宿主机目录权限为 999:999、服务端与初始化脚本及连接层统一 utf8mb4 字符集,且初始化 SQL 仅在空数据目录下执行一次。
docker-compose.yml 文件配对了就能跑,但多数人卡在中文乱码、初始化不生效、数据不持久这三处。直接上可落地的解法。
别用 mysql:latest 或 mysql:8 —— 最新镜像的 latest 会随时间漂移,8.x 大版本间存在默认认证插件变更(mysql_native_password vs caching_sha2_password),导致客户端连不上。
mysql:8.0.33,它稳定、文档全、兼容主流驱动command 中加 --default-authentication-plugin=mysql_native_password 是临时补救,不是根治方案只写 volumes: - ./data:/var/lib/mysql 不够,还要确保宿主机目录权限正确。MySQL 容器内以 UID 999(mysql 用户)运行,若宿主机 ./data 目录属主是 root,容器启动会失败并报错:mysqld: Can't create/write to file '/var/lib/mysql/is_writable'。
sudo chown -R 999:999 ./data
/var/lib/mysql 挂成只读(ro),否则初始化脚本和后续写入全失败只改 my.cnf 或只设 command 参数,都不够。乱码本质是字符集链路断在某一处。
character-set-server=utf8mb4 和 collation-server=utf8mb4_unicode_ci
init.sql)本身必须用 UTF-8 with BOM(或无 BOM)编码保存,Windows 记事本默认带 BOM,Linux vim 默认无 BOM,推荐用 VS Code 确认编码SET NAMES utf8mb4; —— 这行不能省,它告诉 MySQL 当前连接用什么字符集通信mysql -uroot -p -e "SHOW VARIABLES LIKE 'character%';",确认 character_set_server 和 collation_server 均为 utf8mb4
这是最常被忽略的机制:Docker 最新镜像只在 /var/lib/mysql 为空时,才执行 /docker-entrypoint-initdb.d/*.sql。改了 SQL 想重跑?删卷再启,不是 docker-compose restart。
docker-compose down -v(-v 删除关联的数据卷)mysql -uroot -p -e "DROP DATABASE IF EXISTS your_db; CREATE DATABASE your_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
./initdb:/docker-entrypoint-initdb.d)比单文件更灵活,文件按字母序执行,建议用 01-create-tables.sql、02-insert-data.sql 命名MySQL 在容器里跑得稳不稳,关键不在“能不能起来”,而在“数据会不会丢”、“中文会不会变问号”、“下次重装还能不能复现”。每一步的副作用都得提前想清楚,比如 chown 999 看似小操作,漏了整条链就断。