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:00Docker Compose搭MySQL,真正卡住的往往不是语法,而是密码策略、路径权限、时区层级、网络命名这些“隐性契约”。每加一个容器,就得重新核对一次
container_name、
depends_on顺序、
healthcheck超时——它们不报错,但会让服务看起来“启动了”,实际不可用。
