mysql容器跳过/init.sql执行,根本原因是/var/lib/mysql非空导致database_already_exists为true,使/docker-entrypoint-initdb.d/脚本被忽略;常见诱因包括未清理数据卷、挂载路径错误、文件权限不足(如600)、utf-8 bom头或sql语法错误致脚本中断。

脚本不执行,几乎总是因为 MySQL 容器跳过了初始化阶段——它认为“数据库已经存在”,直接启动服务,根本不看 /docker-entrypoint-initdb.d/ 下的文件。
为什么容器跳过 init.sql 执行
MySQL 官方镜像只在 /var/lib/mysql 目录为空时才执行初始化脚本。一旦该目录(通常是挂载的宿主机路径,比如 ./mysql-data)里有文件(哪怕只是隐藏的 .gitkeep 或残留的 ibdata1),DATABASE_ALREADY_EXISTS 就会被设为 true,整个 /docker-entrypoint-initdb.d/ 目录被忽略。
- 最常见诱因:反复
docker-compose up后没清数据卷,./mysql-data已非空 - 容易被忽略:你改了
init.sql内容,但没删数据目录,新脚本压根不加载 - 注意:
depends_on和容器状态为Up≠ 数据库初始化完成,它连“是否执行过脚本”都不检查
挂载路径写错或权限不对
即使数据目录是空的,挂载本身出问题也会让脚本静默失效。
-
volumes必须显式写成./init.sql:/docker-entrypoint-initdb.d/init.sql,不能是./init.sql:/sql/init.sql或./init:/docker-entrypoint-initdb.d/(后者少了个/尾部斜杠,Docker 会当成文件而非目录挂载) - 宿主机上的
init.sql文件权限需为可读(644),若为600且属主不是 root,容器内可能读不到 - Windows 用户注意:路径分隔符用
/,不要用\;WSL 下也要确认文件不在 Windows 挂载区(如/mnt/c/),否则可能因权限模型不兼容导致读取失败
SQL 脚本本身触发中断
脚本只要有一行报错(哪怕只是语法错、表已存在、字符集不匹配),后续所有语句全部停止执行,且日志里可能只显示一行错误,其余“无声失败”。
- 典型错误:
ERROR 1045 (28000): Access denied—— 脚本里写了mysql -uapp -p... -e "...",但初始化阶段只允许mysql -uroot -p"$MYSQL_ROOT_PASSWORD" - 建库语句冗余:
CREATE DATABASE IF NOT EXISTS app_db没必要,因为MYSQL_DATABASE=app_db已自动创建,重复建库不会报错,但若加了USE app_db反而可能因上下文失效出错 - 编码陷阱:文件带 UTF-8 BOM 头,首字节
\xEF\xBB\xBF被当命令解析,直接报Unknown command '\xEF'
真正麻烦的不是“怎么让它跑起来”,而是“它看起来跑过了,但结果不对”——比如表结构对了、数据却没插进去,大概率是脚本中途断了,或者你误以为 MYSQL_DATABASE 环境变量会自动执行你的 init.sql,其实它俩完全独立。











