用 docker run 启动官方 MySQL 镜像是最稳妥起点,但必须指定 MYSQL_ROOT_PASSWORD、挂载数据卷 /var/lib/mysql 并暴露端口,否则重启丢数据;初始化脚本放 /docker-entrypoint-initdb.d 仅首次生效;MySQL 8.0 默认认证插件不兼容旧客户端,需显式设为 mysql_native_password。

直接说结论:用 docker run 启动官方 mysql 镜像是最稳妥的起点,但跳过初始化配置、暴露默认端口、不挂载数据卷这三步,容器重启后数据就丢了。
如何拉取并运行一个可用的 MySQL 容器
别用第三方镜像,优先选官方 mysql:8.0 或 mysql:5.7(根据应用兼容性定)。启动时必须指定 root 密码,否则容器会启动失败并退出:
docker run -d \ --name mysql-dev \ -e MYSQL_ROOT_PASSWORD=123456 \ -p 3306:3306 \ -v /mydata/mysql:/var/lib/mysql \ -v /mydata/mysql/conf:/etc/mysql/conf.d \ mysql:8.0
-
MYSQL_ROOT_PASSWORD是必设环境变量,没有它容器日志里会报ERROR 1045 (28000): Access denied并退出 -
-v /mydata/mysql:/var/lib/mysql这个挂载不能省,否则容器删了,数据库文件全在容器里一并清空 -
-v /mydata/mysql/conf:/etc/mysql/conf.d是为了后续加my.cnf调参,比如改max_connections或字符集
为什么连不上刚起的 MySQL 容器
常见原因不是端口没暴露,而是 MySQL 8.0 默认用了 caching_sha2_password 插件,老客户端(如 MySQL 5.7 客户端、某些 Python pymysql 版本)直连会报 Authentication plugin 'caching_sha2_password' cannot be loaded。
- 临时解法:启动时加
-e MYSQL_DEFAULT_AUTHENTICATION_PLUGIN=mysql_native_password - 长期建议:进容器执行
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; - 注意:如果用
-e MYSQL_ROOT_HOST=%开放远程访问,必须配合FLUSH PRIVILEGES;,否则连本地 host 也拒绝
如何让容器启动时自动执行建库/建表脚本
Docker 官方镜像支持 /docker-entrypoint-initdb.d 目录下的 .sql、.sh 文件,但只在容器**首次初始化数据目录时**执行(即 /var/lib/mysql 为空时):
- 把
init.sql放到宿主机目录,例如/mydata/mysql/init/init.sql - 启动命令加挂载:
-v /mydata/mysql/init:/docker-entrypoint-initdb.d - 脚本里不要写
CREATE DATABASE IF NOT EXISTS—— 因为 init 目录只在空数据目录时触发,此时库肯定不存在;重复挂载该目录再启容器,脚本不会重跑 - 如果想每次启动都执行,得自己写 entrypoint 脚本替换掉原镜像的
docker-entrypoint.sh
数据卷权限和 SELinux 常见坑
在 CentOS/RHEL 主机上,Docker 容器内 MySQL 进程(uid=999)可能无权写宿主机挂载的目录,表现为容器反复重启、日志卡在 Starting MySQL:
- 检查挂载目录权限:
ls -ld /mydata/mysql,应允许 group/o 写入,或直接chown -R 999:999 /mydata/mysql - SELinux 启用时,需加
:z标签:-v /mydata/mysql:/var/lib/mysql:z,否则Permission denied - Mac 或 Windows Docker Desktop 没这问题,但要注意 Docker Desktop 的文件共享设置是否包含你的挂载路径
最易被忽略的是:MySQL 容器停掉后,如果直接 docker rm 再 run,只要数据卷还在,就仍是同一套数据;但若误删了 /mydata/mysql 目录,所有表结构和数据彻底不可逆丢失——备份策略和挂载路径管理比启动命令本身更重要。










