mysql容器化部署需配置网络互通、权限开放、时区字符集统一:使用自定义网络、–bind-address=0.0.0.0、create user…’%’、my.cnf设lower_case_table_names=1及default-time-zone=’+08:00’,jdbc url显式指定servertimezone=gmt%2b8和characterencoding=utf8mb4。

MySQL 容器化部署:用 docker 快速起一个可连通的实例
微服务本地开发阶段,不需要搭完整高可用集群,docker run 一条命令就能拉起一个带初始化数据、开放端口、支持远程连接的 MySQL 实例。关键不是“装 MySQL”,而是让它能被其他服务(比如 spring Boot 的 user-service)立刻连上。
- 必须加
--network host或自定义桥接网络(推荐--network mynet),否则默认 bridge 网络下容器间 DNS 不通,spring.datasource.url=jdbc:mysql://mysql:3306/db里的mysql会解析失败 - 挂载配置文件比用
-e MYSQL_ROOT_PASSWORD更可控:把自定义my.cnf放进/etc/mysql/conf.d/,启用lower_case_table_names=1避免大小写敏感导致 JPA 表名映射异常 - 首次启动时用
-v ./init.sql:/docker-entrypoint-initdb.d/init.sql自动执行建库建用户,其中CREATE USER 'svc'@'%' IDENTIFIED BY 'pwd'; GRANT ALL ON mydb.* TO 'svc'@'%';是后续服务连接必需的
spring boot 服务注册到 Nacos 时连不上 MySQL 的典型原因
不是 Nacos 配置错了,而是 application.yml 里数据库连接参数和实际容器网络不匹配。Nacos 控制台能看到服务上线,但服务日志反复报 Communications link failure,基本锁定在 JDBC URL 解析或权限问题。
-
spring.datasource.url中的 host 不能写localhost或127.0.0.1——这是容器内部的回环地址,要写宿主机 IP(如192.168.1.100)或 Docker 网络别名(如mysql),前提是两者在同一个--network - Nacos 注册的服务元数据(
ip和port)由spring.cloud.nacos.discovery.ip控制,默认会取网卡第一个非 loopback 地址,若宿主机有多个网卡(比如 VirtualBox 虚拟网卡),可能选错,必须显式指定 - 检查 MySQL 容器日志:
docker logs mysql,出现Host '172.18.0.3' is not allowed to connect to this MySQL server就说明用户没开@'%'权限,或者bind-address = 127.0.0.1没改成0.0.0.0
多服务共用一套 MySQL 时的 schema 隔离策略
本地联调阶段,order-service 和 payment-service 不该共用同一张 orders 表,但也不必为每个服务单独部署 MySQL 实例。用 database 级隔离最轻量,且兼容 mybatis / JPA 的默认行为。
- 初始化 SQL 中为每个服务创建独立 database:
CREATE DATABASE order_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;,对应服务的spring.datasource.url指向自己的库,如jdbc:mysql://mysql:3306/order_db - 避免跨库 JOIN:JPA 的
@SecondaryTable或 MyBatis 的<select></select>关联查询在分库后失效,需改用服务间 http 调用(Feign)或事件驱动(rocketmq)获取关联数据 - Flyway 迁移脚本按服务目录组织:
src/main/resources/db/migration/order/V1__init.sql,各服务只扫自己前缀的路径,防止 migration 冲突
Nacos + MySQL 组合调试时最容易忽略的时区与字符集
服务能注册、能连库、SQL 也能执行,但存进去的 timestamp 字段总是差 8 小时,或者中文变 ???——这类问题不会报错,却让业务逻辑出错,排查成本极高。
- MySQL 容器必须加启动参数:
-e TZ=Asia/Shanghai并在my.cnf中设default-time-zone = '+08:00',否则 JDBC 驱动读TIMESTAMP时按 UTC 解析,Spring Boot 的@Createddate就会错 - JDBC URL 必须显式声明字符集:
jdbc:mysql://mysql:3306/mydb?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=GMT%2B8,漏掉serverTimezone参数会导致java.time.LocalDateTime类型字段插入为null - Docker Compose 启动时,MySQL 和应用服务的
environment都要配TZ=Asia/Shanghai,否则 jvm 默认时区是 UTC,new Date()和数据库时间对不上
本地跑通不代表生产可用,但所有环境差异几乎都集中在网络可见性、权限粒度、时区字符集这三处。少一个 %、多一个 127.0.0.1、漏一个 utf8mb4,就卡半天。