Docker-Compose 部署 MySQL 8 并解决中文乱码问题
2026/6/26 5:13:50 网站建设 项目流程

在开发环境中,使用 Docker Compose 可以快速搭建 MySQL 环境。

但使用挂在目录方式让Docker-MySQL自动执行挂载到目录(/docker-entrypoint-initdb.d)中的初始化脚本, 导入含有中文数据的 SQL 时,我遇到了令人头疼的乱码问题。

咨询了AI, 测试了各种方案之后, 总算解决了这个问题。

本文将完整介绍如何用docker-compose.yml部署mysql:8.0.33,以及如何挂载初始化 SQL,并彻底解决中文乱码问题。

文章目录

    • @[toc]
    • 一、基础配置:指定 mysql:8.0.33 镜像
    • 二、映射 /docker-entrypoint-initdb.d 目录指定初始化 SQL
    • 三、避免乱码:服务端字符集配置
    • 四、初始化 SQL 文件本身的编码
    • 五、完整的 docker-compose.yml 示例
    • 六、最后的关键一步:在 SQL 文件中加上 `SET NAMES utf8mb4;`
      • 6.1 加上这一行后,中文乱码得到了彻底解决!
    • 七、验证字符集是否生效
    • 小结

一、基础配置:指定 mysql:8.0.33 镜像

首先,我们在docker-compose.yml文件中明确指定 MySQL 镜像版本。

一定要锁定具体版本号(如8.0.33),而不是使用latest或宽泛的8.0,以保证多台机器、多次部署的一致性。

生产环境根据情况确定, 一般不推荐使用Docker来部署。

services:mysql:image:mysql:8.0.33container_name:my-mysqlrestart:unless-stoppedenvironment:MYSQL_ROOT_PASSWORD:123456MYSQL_DATABASE:local_databaseTZ:Asia/Shanghaiports:-"3306:3306"

二、映射 /docker-entrypoint-initdb.d 目录指定初始化 SQL

MySQL 官方镜像提供了一个非常实用的机制:容器首次启动且数据目录为空时,会自动执行/docker-entrypoint-initdb.d目录下的所有.sql.sql.gz.sh文件。

我们只需将本地的初始化 SQL 文件挂载到该目录即可:

volumes:# 持久化数据-mysql_data:/var/lib/mysql# 挂载单个初始化 SQL(关键)-./init.sql:/docker-entrypoint-initdb.d/init.sql

也可以挂载整个目录,让多个 SQL 文件按文件名顺序执行:

volumes:-./initdb:/docker-entrypoint-initdb.d

⚠️重要提醒:初始化脚本只在数据目录为空时执行一次。如果你修改了 SQL 想重新初始化,需要先删除数据卷:

docker-composedown-v

三、避免乱码:服务端字符集配置

乱码的本质是字符集不统一

MySQL 8.0 默认字符集虽然已经是utf8mb4,但为了万无一失,需要在服务端、客户端层面都显式声明。

通过command直接指定服务端字符集:

command:---character-set-server=utf8mb4---collation-server=utf8mb4_unicode_ci

如果你想用配置文件管理,可以挂载一个自定义的my.cnf

# my.cnf [mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci [client] default-character-set=utf8mb4 [mysql] default-character-set=utf8mb4
volumes:-./my.cnf:/etc/mysql/conf.d/my.cnf

其中[client][mysql]这两段尤其重要,因为容器在执行/docker-entrypoint-initdb.d里的 SQL 时,正是通过内置的mysql客户端导入的。如果客户端连接字符集不对,导入的中文就会乱码。


四、初始化 SQL 文件本身的编码

除了 MySQL 的配置,还要确保 SQL 文件本身的物理编码正确:

  • 文件必须保存为 UTF-8 编码(无 BOM)
  • 不要使用 GBK、ANSI 等编码保存含中文的 SQL 文件

可以用编辑器(如 VS Code)右下角确认并切换编码格式。


五、完整的 docker-compose.yml 示例

services:mysql:image:mysql:8.0.33container_name:my-mysqlrestart:unless-stoppedcommand:---character-set-server=utf8mb4---collation-server=utf8mb4_unicode_cienvironment:MYSQL_ROOT_PASSWORD:123456MYSQL_DATABASE:local_databaseTZ:Asia/Shanghaiports:-"3306:3306"volumes:-mysql_data:/var/lib/mysql-./init.sql:/docker-entrypoint-initdb.d/init.sqlvolumes:mysql_data:

六、最后的关键一步:在 SQL 文件中加上SET NAMES utf8mb4;

在完成了上面所有配置后,我以为乱码问题已经解决,但实际导入时中文依然出现乱码。经过反复排查,我在初始化 SQL 文件的最开头加上了这一行:

SETNAMES utf8mb4;
-- init.sqlSETNAMES utf8mb4;CREATETABLEIFNOTEXISTS`user`(`id`INTPRIMARYKEYAUTO_INCREMENT,`name`VARCHAR(50)NOTNULL)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;INSERTINTO`user`(`name`)VALUES('张三'),('李四'),('王五');

6.1 加上这一行后,中文乱码得到了彻底解决!

为什么这一步如此关键?因为SET NAMES utf8mb4;同时设置当前连接会话的三个核心字符集变量

  • character_set_client(客户端发送数据的字符集)
  • character_set_connection(连接层的字符集)
  • character_set_results(返回结果的字符集)

即使前面服务端和配置文件都做了设置,但初始化导入这个会话如果没有显式声明连接字符集,仍可能因默认值不匹配导致中文在传输过程中被错误解码。SET NAMES utf8mb4;直接在 SQL 执行的会话层面"一锤定音",从源头保证了中文数据以 utf8mb4 正确写入。


七、验证字符集是否生效

部署完成后,进入容器验证:

dockerexec-itmy-mysql mysql-uroot-p\-e"SHOW VARIABLES LIKE 'character%';"

确认以下变量均为utf8mb4

  • character_set_server
  • character_set_database
  • character_set_client
  • character_set_connection

再查询数据,确认中文显示正常:

SELECT*FROMuser;

小结

最终在 SQL 文件首行加上SET NAMES utf8mb4;,才让中文乱码问题得到了彻底、干净的解决。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询