Docker 部署 MySQL 9.2.0:搞定中文乱码与时区
背景与目标
相比 SQL Server,MySQL 在个人电脑上"装起来没那么痛苦",但也逃不过那几个经典系统级问题:服务注册冲突、端口被占、卸载不干净、还有最烦的字符集乱码和时区不对——数据库看着装好了,一写中文就变 ???,查个时间又差 8 个小时。
这些其实都是"启动参数"问题,不是数据库装错了。用 Docker 部署 MySQL,把字符集、时区、端口、认证方式全部在你可见的 docker-compose.yaml 里一次定好,可复现、可删可重来。本文给你一份验证用的配置,开箱即用。
提示:本文作者宿主是 Windows (Docker Desktop)。镜像通过华为云镜像站拉取(国内拉取更快更稳)。
步骤
第 0 步:确认 Docker Desktop 已就绪
docker version
docker compose version输出版本号即 OK。
第 1 步:准备目录
mkdir mysql && cd mysql第 2 步:写 docker-compose.yaml
新建 docker-compose.yaml,整段复制:
services:
mysql:
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/mysql:9.2.0
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: "YourStrong!Passw0rd"
MYSQL_TZ: "Asia/Shanghai"
TZ: "Asia/Shanghai"
LANG: "C.UTF-8"
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --default-time-zone=+8:00
ports:
- "3306:3306"
volumes:
- ./mysql-data:/var/lib/mysql
restart: unless-stopped要点:
MYSQL_ROOT_PASSWORD:root 密码,务必设一个强密码。字符集
utf8mb4+ 排序规则utf8mb4_unicode_ci:中文不乱的根源。时区双保险:环境变量
TZ+ 服务参数--default-time-zone=+8:00。数据卷
./mysql-data绑定挂载,数据落盘。
第 3 步:启动
docker compose up -d首次启动 MySQL 要初始化数据目录,需要一点时间。看日志:
docker compose logs -f mysql看到 ready for connections 即就绪。
第 4 步:连接验证
进容器用命令行连:
docker compose exec mysql mysql -uroot -p输入密码(就是 MYSQL_ROOT_PASSWORD)。能进到 mysql> 提示符即成功。
验证字符集和时区:
SHOW VARIABLES LIKE 'character_set_server';
SELECT NOW();character_set_server 应为 utf8mb4,NOW() 应显示北京时间。
踩坑与解决
1. 连接报 Authentication plugin 'caching_sha2_password' cannot be loaded
问题:用一些老客户端 / 旧版程序连不上,报 authentication plugin 错误。
复现:旧版 JDBC 驱动或老 Navicat 连接时报
caching_sha2_password ... cannot be loaded。根因:MySQL 8.0+ 默认认证插件是
caching_sha2_password,早于 8.0 的客户端不认识它。解决:a) 升级客户端到支持 MySQL 8/9 的版本(推荐);b) 确实没法升级时,为特定用户降级为
mysql_native_password:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourStrong!Passw0rd';验证:旧客户端能正常连接。
2. 中文变成 ??? / 乱码
问题:插入中文查询出来全是问号。
复现:
INSERT中文后SELECT显示???。根因:默认字符集或排序规则不是 utf8mb4。注意
utf8在 MySQL 里其实是utf8mb3,存不全四字节字符。解决:本教程的 yaml 已用
--character-set-server=utf8mb4和--collation-server=utf8mb4_unicode_ci。若已有库建错了,保证库表和连接串都用utf8mb4,并确认连接用SET NAMES utf8mb4(或 JDBC 连接参数characterEncoding=utf8)。验证:插入中文后
SELECT正常显示。
3. 时间比北京时间差 8 小时
问题:
NOW()返回的是 UTC 时间,比本地慢 8 小时。复现:应用存的"当前时间"与本地时间不符。
根因:容器默认时区是 UTC,未设
TZ。解决:yaml 已设环境变量
TZ=Asia/Shanghai+MYSQL_TZ+ 服务参数--default-time-zone=+8:00三重保证。若容器已启动,改配置后docker compose up -d重建。验证:
SELECT NOW()返回北京时间。
4. 数据丢了?(重启后表消失)
问题:删容器重建后,之前建的数据没了。
复现:
docker compose down && docker compose up -d后库里是空的。根因:没挂数据卷,数据存在容器可写层,容器销毁即丢失。
解决:yaml 已挂
./mysql-data:/var/lib/mysql绑定卷。数据持久化在你目录下的mysql-data/。验证:建个测试表,
docker compose down再up,表仍在。
5. 端口 3306 被占
问题:
docker compose up -d报端口被占用。复现:报
port is already allocated或address already in use。根因:本机已有 MySQL 服务或其他程序占用 3306。
解决:改外部端口,如
3307:3306;连接时用localhost:3307。或停掉本机残留的 MySQL 服务。验证:
docker compose up -d成功,客户端连新端口正常。
实操截图
容器运行

连接数据库


小结与参考
用 Docker 部署 MySQL 9.2.0,把字符集、时区、认证一次性在配置里定好,可复现、可重来。
字符集必用
utf8mb4(别用会截断中文符号的utf8),时区设Asia/Shanghai。MySQL 8.0+ 默认
caching_sha2_password,老客户端连不上时优先升级客户端。数据卷挂
./mysql-data,容器销毁不丢数据。端口被占改外部端口即可。
参考:
镜像:
swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/mysql:9.2.0

