必须挂载 /var/lib/mysql 目录,否则容器重启后数据丢失;root 密码需通过 -e mysql_root_password 设置;端口映射用 -p 3306:3306;初始化脚本挂载到 /docker-entrypoint-initdb.d/ 且仅首次执行。

docker run 启动 mysql 容器时必须挂载 /var/lib/mysql
不挂载数据目录,容器重启后所有数据库、表、用户都会消失——这是最常踩的坑。MySQL 镜像默认把数据写在容器内部的 /var/lib/mysql,而容器删除即销毁该路径。
实操建议:
- 用
-v /host/path:/var/lib/mysql显式绑定宿主机目录,例如-v ./mysql-data:/var/lib/mysql - 首次运行前确保宿主机目录为空(或由 MySQL 初始化过),否则启动失败并报错
mysqld: Can't read dir of '/etc/mysql/conf.d/'或权限拒绝 - Linux 下宿主机目录需给
chown -R 999:999 ./mysql-data(MySQL 官方镜像以 UID 999 运行 mysqld)
root 密码必须通过 MYSQ_ROOT_PASSWORD 环境变量传入
官方 mysql 镜像不接受命令行参数设密码,也不读取配置文件里的 password 字段。漏设该变量会导致容器卡在初始化阶段,日志反复输出 Waiting for MySQL to start...。
实操建议:
- 必须加
-e MYSQ_ROOT_PASSWORD=your_secure_password,不能写成MYSQL_ROOT_PASSWORD(少个S就无效) - 密码含特殊字符(如
@、$)要对 shell 做转义,或改用--env-file文件方式传入 - 如果后续想换密码,不要删容器重跑,应进容器执行
ALTER USER 'root'@'%' IDENTIFIED BY 'newpass';
端口映射和远程访问需要额外开 MYSQL_ROOT_HOST
默认只允许 root@localhost 登录,宿主机用 mysql -h 127.0.0.1 -P 3306 -u root -p 会连不上,报错 Access denied for user 'root'@'172.17.0.1'(Docker 网络分配的 IP)。
实操建议:
- 加
-e MYSQL_ROOT_HOST=%允许任意 host 连接 root(仅开发环境用;生产请建专用用户) - 务必配
-p 3306:3306,注意左边是宿主机端口,右边是容器内端口,顺序反了没报错但连不通 - 若宿主机 3306 已被占用,可映射为
-p 3307:3306,但客户端连接时必须指定-P 3307
初始化 SQL 脚本得放对位置:容器启动时自动执行 /docker-entrypoint-initdb.d/
把 init.sql 直接丢进挂载的数据目录不会生效——MySQL 启动时只扫描 /docker-entrypoint-initdb.d/ 下的 .sql、.sh、.sql.gz 文件,且**仅当数据目录为空时执行一次**。
实操建议:
- 用
-v ./init.sql:/docker-entrypoint-initdb.d/init.sql挂载脚本(注意路径拼写,少一个/就变成创建同名文件而非挂载) - 脚本里别写
CREATE DATABASE—— 官方镜像已根据MYSQL_DATABASE环境变量建库;重复建库会中断初始化 - 如果容器已运行过,再挂脚本也不会执行;删容器 + 清空数据目录 + 重跑才是唯一触发方式
真正麻烦的不是命令写不对,而是数据目录权限、初始化时机、网络访问策略这三者交织在一起——调通一次之后,下次换机器或升级镜像版本,很可能因为 UID 变了或 MySQL 版本行为微调,又卡在同一个地方。










