真正“一键可用”的关键在于挂载my.cnf(含utf8mb4与mysql_native_password配置)、init.sql(建库授权并指定字符集)及数据目录(uid需为999),三者缺一不可;仅docker run -e启动必在hive连接、中文乱码、数据丢失上失败。

直接上结论:用 docker run 一条命令就能跑起来,但只靠这条命令,90% 的人会在 Hive 连接、中文乱码、远程访问失败上卡住。真正“一键可用”的关键不在启动命令本身,而在配置文件、初始化脚本和挂载路径的组合。
为什么 docker run -e MYSQL_ROOT_PASSWORD=xxx mysql:8.0 不够用?
这条命令能启动容器,但默认配置会立刻暴露三个硬伤:
-
character-set-server是latin1,init.sql里建库用utf8mb4会失效 - MySQL 8.0 默认认证插件是
caching_sha2_password,Hive JDBC 驱动(尤其老版本)不认,连不上 - 容器内
/var/lib/mysql没挂载宿主机目录,docker rm一执行,所有表结构和数据全丢
my.cnf 必须显式挂载,且要包含这三行
不能只靠环境变量覆盖编码和时区。Docker 官方镜像不会自动读取你放在任意位置的 my.cnf —— 必须挂载到 /etc/mysql/conf.d/ 下,且文件名以 .cnf 结尾。
最小有效配置只有这三行(其他参数可后续加):
[mysqld] character-set-server=utf8mb4 default-authentication-plugin=mysql_native_password [client] default-character-set=utf8mb4
注意:default-authentication-plugin 这一行决定 Hive 能不能连;[client] 段影响 mysql 命令行客户端默认编码,否则即使服务端是 utf8mb4,本地登录后 show variables like 'char%' 仍可能显示 latin1。
初始化脚本 init.sql 要在容器首次启动时生效
Docker MySQL 镜像只在 /docker-entrypoint-initdb.d/ 目录下执行 .sql 或 .sh 文件,且**仅当 /var/lib/mysql 为空时才执行一次**。这意味着:
- 如果已挂载非空目录,
init.sql永远不会运行 —— 别指望它反复建库授予权限 -
CREATE USER IF NOT EXISTS在 MySQL 8.0 中必须配合IDENTIFIED WITH mysql_native_password,否则用户创建成功但认证方式仍是caching_sha2_password - Hive 元数据库名不能含下划线以外的特殊字符,
hive-metastore会报语法错,必须用hive_metastore
所以 init.sql 至少得写成这样:
-- 必须用 utf8mb4 显式指定 CREATE DATABASE IF NOT EXISTS hive_metastore DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER IF NOT EXISTS 'hive'@'%' IDENTIFIED WITH mysql_native_password BY 'root123'; GRANT ALL ON hive_metastore.* TO 'hive'@'%'; FLUSH PRIVILEGES;
挂载路径和权限最容易被忽略
宿主机目录权限不对,MySQL 容器启动直接退出,日志里只报 Permission denied,不告诉你具体哪个文件。
-
/var/lib/mysql对应的宿主机目录(如/mydata/mysql/data)必须属主为 UID 999(MySQL 容器内默认用户mysql的 UID),不是 root - 用
chown -R 999:999 /mydata/mysql/data,而不是chmod 777—— 后者反而触发 MySQL 安全拒绝 -
/etc/mysql/conf.d/my.cnf挂载时,宿主机文件权限建议644,否则容器内读不到 - 不要把整个
/etc/mysql挂载成目录,会覆盖镜像里原有的mysql.conf.d/,导致启动失败
最终能稳定跑通 Hive 元存储的完整启动命令长这样:
docker run -d \ --name mysql-hive \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=root123 \ -v /mydata/mysql/data:/var/lib/mysql \ -v /mydata/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf \ -v /path/to/init.sql:/docker-entrypoint-initdb.d/init.sql \ mysql:8.0
复杂点从来不在“怎么启动”,而在于:挂载目录的 UID 是否匹配、my.cnf 是否落在正确路径、init.sql 是否在首次启动前就位 —— 这三处任一出错,容器都起得来,但 Hive 死活连不上。











