mysql容器启动失败主因是未设置mysql_root_password;数据持久化需挂载/var/lib/mysql;时区需同时配置tz和–default-time-zone;多实例须设container_name并自定义network。

MySQL容器启动失败:检查MYSQL_ROOT_PASSWORD是否缺失或为空
不设密码是mysql:8.0+镜像启动失败的最常见原因。docker官方MySQL镜像强制要求设置MYSQL_ROOT_PASSWORD,否则容器会立即退出并报错:Error 1045 (28000): access denied for user 'root'@'localhost'(实际是启动阶段校验失败,不是连接失败)。
实操建议:
-
environment下必须显式声明MYSQL_ROOT_PASSWORD,不能依赖.env文件未定义时的空值 - 避免使用纯数字或常见弱密码(如
123456),MySQL 8.0+默认密码策略会拒绝太简单的密码 - 若需初始化数据库结构,可配合
volumes挂载.sql文件到/docker-entrypoint-initdb.d/
多个MySQL服务共存:用container_name和networks隔离实例
在单个docker-compose.yml中定义多个MySQL服务(比如mysql-master和mysql-slave)时,不能只靠服务名通信——默认bridge网络下DNS解析的是服务名,但MySQL客户端默认连接localhost,而localhost在容器内指向127.0.0.1,不是服务发现地址。
实操建议:
- 为每个MySQL服务显式设置
container_name(如mysql-master-1),方便其他容器直连 - 自定义
networks并指定driver: bridge,避免与默认网络混淆 - 应用容器连接时,host应写成
mysql-master-1而非mysql-master(后者是服务名,不是容器名,除非你没设container_name) - 主从复制场景下,务必在
command中覆盖默认启动命令,加入--server-id=1等参数
数据持久化失效:确认volumes路径映射到MySQL数据目录
MySQL容器重启后数据丢失,大概率是volumes没挂载对位置。MySQL 8.0+默认数据目录是/var/lib/mysql,不是/data或/db;挂载错路径会导致容器用临时文件系统存储数据。
实操建议:
- 使用绝对路径挂载,例如
./mysql-data:/var/lib/mysql:rw,不要用相对路径mysql-data:/var/lib/mysql(后者会被当作命名卷,无法直接查看宿主机文件) - 首次运行前确保宿主机目录权限正确:
chown -R 999:999 ./mysql-data(MySQL容器内用户UID为999) - 若已启动过容器再加挂载,先
docker-compose down -v清空匿名卷,否则旧数据仍留在卷里,新挂载不生效
时区不一致导致查询结果异常:通过environment和command统一设置
MySQL容器默认UTC时区,而应用容器可能是Asia/Shanghai,执行NOW()、CURDATE()等函数时返回时间差8小时,排查困难。
实操建议:
- 在
environment中添加TZ: Asia/Shanghai(影响OS层时区) - 同时在
command中追加--default-time-zone='+08:00'(影响MySQL服务层时区) - 验证方式:进入容器执行
mysql -uroot -p -e "select @@global.time_zone, @@session.time_zone;",两个值都应为+08:00
Docker Compose搭MySQL,真正卡住的往往不是语法,而是密码策略、路径权限、时区层级、网络命名这些“隐性契约”。每加一个容器,就得重新核对一次container_name、depends_on顺序、healthcheck超时——它们不报错,但会让服务看起来“启动了”,实际不可用。