必须加-v挂载数据目录、-e设强密码、-e指定字符集,否则容器可运行但连不上、存不了中文、重启丢数据;宿主机目录需为空且权限正确,密码须含大小写字母数字特殊字符,配置文件需挂载utf8mb4及mysql_native_password插件。

直接上结论:用 docker run 启动容器是最简单可靠的方式,但必须挂载数据目录、设强密码、指定字符集,否则容器一删,库就丢,连登录都可能失败。
docker run 启动 MySQL 8.0 容器时必须加哪些参数
不加关键参数,容器能跑起来,但大概率连不上、存不了中文、重启后数据消失。核心参数缺一不可:
-
-v /mydata/mysql/data:/var/lib/mysql:必须挂载数据目录,/mydata/mysql/data是宿主机路径,提前mkdir -p /mydata/mysql/data创建好,且确保权限可写(MySQL 容器内以 UID 999 运行) -
-e MYSQL_ROOT_PASSWORD=YourStrongPassw0rd:MySQL 8.0 强制要求 root 密码,且不能是简单字符串(如123456),否则容器启动失败并报错ERROR 1045 (28000): Access denied for user 'root'@'localhost' -
-e MYSQL_DATABASE=app_db和-e MYSQL_USER=app_user+-e MYSQL_PASSWORD=UserPass123:如果需要预建应用库和用户,这三者要一起用,否则只设MYSQL_USER不设MYSQL_DATABASE,用户会被创建但无库可连 -
--restart unless-stopped:防止 Docker 服务重启后 MySQL 容器没起来,开发/测试环境别用always,否则日志刷屏停不下来
为什么连不上 3306?端口映射和网络配置常见问题
执行 docker ps 能看到容器在运行,但本地 mysql -h127.0.0.1 -P3306 -uroot -p 报 Can't connect to MySQL server,多数是以下原因:
- 漏了
-p 3306:3306:仅-p 3306是无效的,必须写成hostPort:containerPort格式 - 防火墙拦截:Linux 上检查
sudo ufw status或sudo firewall-cmd --list-ports,确认 3306 开放;macOS/Windows Docker Desktop 默认放行,不用额外处理 - MySQL 8.0 默认绑定
127.0.0.1:容器内默认只监听 localhost,外部无法访问,需通过-e MYSQL_ROOT_HOST=%允许任意主机连接(仅测试环境用,生产请限定 IP) - 连接时用了错误 host:Mac 上用
host.docker.internal,Linux 需加--add-host host.docker.internal:host-gateway才能解析该域名
如何让 MySQL 8.0 支持 utf8mb4 和远程客户端连接
不改配置,插入 emoji 或四字节 UTF-8 字符会报错 Incorrect string value,Java/Python 客户端也可能抛 Unknown system variable 'tx_isolation' —— 这是驱动兼容性问题,靠配置文件解决:
- 创建自定义配置文件
/mydata/mysql/conf/my.cnf,内容至少包含:[mysqld] default_authentication_plugin=mysql_native_password character_set_server=utf8mb4 collation_server=utf8mb4_unicode_ci skip-character-set-client-handshake init_connect='SET NAMES utf8mb4'
- 启动时挂载:
-v /mydata/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf:ro(注意:ro只读,防止容器内误改) -
mysql_native_password是关键:MySQL 8.0 默认用caching_sha2_password,老版本客户端(如 MySQL Workbench 8.0.28 以前、某些 Python mysqlclient)不支持,必须显式切回
容器删了,数据还在吗?持久化最容易忽略的细节
很多人以为 -v 挂载了就万事大吉,结果删容器后发现 /mydata/mysql/data 目录是空的——根本原因是容器第一次启动时,MySQL 初始化逻辑会检测 /var/lib/mysql 是否为空,若为空才初始化;如果宿主机目录已有残留文件(比如之前没清干净的 socket 或临时表),MySQL 会跳过初始化,导致服务起不来,且不会报明显错误。
安全做法只有两个:
- 首次部署前,确保
/mydata/mysql/data是空目录(rm -rf /mydata/mysql/data && mkdir -p /mydata/mysql/data) - 删容器前,先
docker stop mysql8,再docker rm mysql8,不要docker rm -f强删,否则可能中断写入造成数据损坏
另外,docker volume create 创建的命名卷虽然更“Docker 原生”,但调试时不如宿主机目录直观,排查日志或手动恢复数据都更麻烦,个人和小团队建议坚持用 -v 绝对路径 方式。


















