不推荐用 docker compose 在生产环境单独部署 mysql 8.0,但若必须用,关键在于数据持久化、字符集固化、启动顺序控制和日志/重启策略这四点,缺一不可;必须锁死 image: mysql:8.0.33 等具体 patch 版本,禁用 latest 或 8.0 标签,同时使用命名卷、utf8mb4 四层对齐、非 root 权限适配及 healthcheck+日志限流。

直接说结论:不推荐用 Docker Compose 在生产环境单独部署 MySQL 8.0,但若必须用,关键在于数据持久化、字符集固化、启动顺序控制和日志/重启策略这四点,缺一不可。
docker-compose.yml 必须显式指定 mysql:8.0.x 而非 mysql:8.0 或 latest
MySQL 官方镜像的 8.0 标签会随小版本更新自动漂移(比如从 8.0.33 升到 8.0.34),而不同小版本间可能存在配置项废弃、默认行为变更(如密码认证插件默认值)、甚至初始化逻辑差异。生产环境要求可重复部署,必须锁死具体 patch 版本。
- ✅ 正确写法:
image: mysql:8.0.33(查 Docker Hub 确认该 tag 存在且为 GA 版) - ❌ 错误写法:
image: mysql:8.0或image: mysql:latest - 注意:社区版用
mysql:8.0.33,企业版需从 My Oracle Support 下载并 load 进本地 registry,不能直接 pull
中文乱码问题不是“加 utf8mb4 就完事”,而是四层叠加校验
常见现象是建库建表时显示正常,但插入中文后查出来是问号或乱码。这不是单点问题,而是服务端、客户端、连接层、初始化 SQL 四层字符集必须对齐。
- 服务端:通过
environment注入MYSQL_INITDB_SKIP_TZINFO=1避免时区初始化失败,并在volumes挂载自定义配置文件/etc/mysql/conf.d/my.cnf,内容含:[mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci skip-character-set-client-handshake
- 客户端连接:应用代码里连接字符串必须带
?charset=utf8mb4(如 JDBC 的useUnicode=true&characterEncoding=utf8mb4) - 初始化 SQL:文件本身保存为 UTF-8 无 BOM 编码,且首行必须写
SET NAMES utf8mb4; - 容器启动时:确保挂载的
conf.d目录权限为 644,否则 MySQL 启动时会静默忽略该配置
数据目录挂载必须用命名卷而非相对路径,且禁止映射 /var/lib/mysql 到 Windows 文件系统
Windows 主机上用 ./mysql/data:/var/lib/mysql 这种绑定挂载,在 Docker Desktop 的 WSL2 后端下极易触发 inode 不一致、文件锁失效,导致 MySQL 启动报错 Can't start server : Bind on unix socket: Permission denied 或反复崩溃。
- ✅ 正确做法:声明命名卷
volumes: mysql_data:,并在 service 中引用- mysql_data:/var/lib/mysql - ✅ 补充加固:添加
command: --default-authentication-plugin=mysql_native_password,避免 8.0 默认的 caching_sha2_password 导致旧客户端连不上 - ⚠️ 注意:命名卷首次创建时为空,MySQL 会自动初始化;若想复用已有数据,需先
docker volume inspect mysql_data查路径,再手动拷贝数据进去(不推荐,易出错)
restart 策略和日志限制是生产可用的底线
容器意外退出后不自动恢复,或日志无限增长占满磁盘,都是线上事故高发点。
-
restart: unless-stopped是底线,不能写always(会导致健康检查失败后无限重启) - 必须配日志驱动限制:
logging: driver: "json-file" options: max-size: "10m" max-file: "3" - 建议加健康检查:
healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"] interval: 30s timeout: 10s retries: 3
(注意密码变量需双 $ 转义)
Docker Compose 部署 MySQL 8.0 最容易被忽略的,其实是 MySQL 进程在容器内以非 root 用户(uid 999)运行,而你挂载的配置文件或初始化 SQL 若属主是 Windows 用户,WSL2 下可能因 uid 映射错乱导致权限拒绝——这时看日志只会看到 mysqld: Can't read dir of '/etc/mysql/conf.d/',根本不会提示权限问题。











