记一次 StreamPark 2.1.5 Docker 部署 MySQL 的完整踩坑与排查记录
摘要:使用 Docker 部署 Apache StreamPark 2.1.5,官方文档和网上教程都说「设置环境变量
SPRING_PROFILES_ACTIVE=mysql+MYSQL_*就能连 MySQL」,结果怎么配都是 H2,数据一重启就丢。本文完整记录从「现象」到「根因」再到「解决」的全过程。
一、背景与问题现象
我需要在测试服务器上用 Docker 部署 StreamPark 来管理 Flink 集群,后端元数据库用 MySQL。
按照网上常见的 docker-compose 写法,给 StreamPark 服务配了这些环境变量:
environment:SPRING_PROFILES_ACTIVE:mysqlMYSQL_HOST:mysqlMYSQL_PORT:3306MYSQL_USERNAME:streamparkMYSQL_PASSWORD:xxxxxxMYSQL_DATABASE:streampark启动后 StreamPark 能正常打开、也能登录,一切都「看起来」正常。直到有一天:
- 我改了 compose 配置(加了个 Flink Home 挂载),
docker stop后docker compose up -d重启; - 重启后发现之前配置的 team(团队)全没了;
- 连进 MySQL 一看,
streampark库里一张表都没有。
这就很奇怪了——明明配的是 MySQL,怎么数据会丢?MySQL 里怎么连表都没有?
二、排查过程
第一步:确认 StreamPark 到底连的是哪个库
看启动日志里数据源相关的内容:
dockerlogs streampark2>&1|grep-iE"jdbc:h2|jdbc:mysql|HikariPool|datasource"日志里出现:
H2 console available at '/h2-console'. Database available at 'jdbc:h2:file:~/streampark/h2-data/metadata'结论:StreamPark 根本没连 MySQL,一直在用 H2 内嵌库。数据存在容器里的~/streampark/h2-data目录,容器一重建就丢,所以 team 没了、MySQL 里自然也没表。
第二步:环境变量明明设了,为什么没用?
确认环境变量确实注入了容器:
dockerexecstreamparkenv|grep-iE"SPRING|MYSQL"输出:
SPRING_PROFILES_ACTIVE=mysql MYSQL_HOST=mysql MYSQL_PORT=3306 MYSQL_USERNAME=streampark MYSQL_PASSWORD=xxxxxx MYSQL_DATABASE=streampark变量都在,但就是没用。于是又尝试了两条更「强力」的方式:
尝试一:用 Spring Boot 原生的SPRING_DATASOURCE_*环境变量。
在docker-compose-streampark.yml的streampark服务里,新增这 4 个变量(Spring Boot 对spring.datasource.url/username/password有 relaxed binding,会自动映射):
environment:TZ:${TZ}SPRING_PROFILES_ACTIVE:mysqlSPRING_DATASOURCE_URL:"jdbc:mysql://mysql:3306/streampark?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"SPRING_DATASOURCE_USERNAME:${MYSQL_USER}SPRING_DATASOURCE_PASSWORD:${MYSQL_PASSWORD}SPRING_DATASOURCE_DRIVER_CLASS_NAME:com.mysql.cj.jdbc.DriverMYSQL_HOST:mysqlMYSQL_PORT:3306MYSQL_USERNAME:${MYSQL_USER}MYSQL_PASSWORD:${MYSQL_PASSWORD}MYSQL_DATABASE:${MYSQL_DATABASE}重启后依旧 H2。
尝试二:用JAVA_TOOL_OPTIONS注入 JVM 系统属性(优先级比环境变量更高)。
同样在environment里加一行:
JAVA_TOOL_OPTIONS:"-Dspring.profiles.active=mysql -Dspring.datasource.url=jdbc:mysql://mysql:3306/streampark?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true -Dspring.datasource.username=${MYSQL_USER} -Dspring.datasource.password=${MYSQL_PASSWORD} -Dspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver"重启后日志里能看到:
Picked up JAVA_TOOL_OPTIONS: -Dspring.profiles.active=mysql -Dspring.datasource.url=jdbc:mysql://...说明 JVM 确实收到了这些-D参数,但StreamPark 依旧用 H2。
到这里基本可以判断:这不是 Spring Boot 标准的数据源配置,StreamPark 走了另一套配置。
第三步:找到真正的启动入口和配置文件
查容器的入口:
dockerinspect streampark--format'{{json .Config.Entrypoint}}'# ["/usr/sbin/tini","--","/streampark/bin/streampark.sh","start_docker"]入口是/streampark/bin/streampark.sh start_docker。查看容器目录,发现关键目录/streampark/conf/下有个config.yaml:
dockerexecstreamparkls-la/streampark/conf/# config.yaml# logback-spring.xml打开config.yaml,真相大白:
datasource:dialect:h2#h2, mysql, pgsqlh2-data-dir:~/streampark/h2-datausername:password:url:StreamPark 的真实数据库配置在config.yaml的datasource.dialect,跟环境变量、Spring profile 一点关系都没有。默认是h2,所以上面那些SPRING_PROFILES_ACTIVE、MYSQL_*、JAVA_TOOL_OPTIONS全都在做无用功。
第四步:改 config.yaml 后,遇到第二个坑——MySQL 驱动找不到
先把容器里原本的 config.yaml 完整拉取下来,只改 datasource 这一段:
mkdir-p/data/streampark/streampark-confdockercpstreampark:/streampark/conf/config.yaml /data/streampark/streampark-conf/config.yaml打开后找到 datasource 段。改前:
datasource:dialect:h2#h2, mysql, pgsqlh2-data-dir:~/streampark/h2-datausername:password:url:改成(其余部分保持不动):
datasource:dialect:mysql#h2, mysql, pgsqlh2-data-dir:~/streampark/h2-data# 仅在 dialect=h2 时生效username:streamparkpassword:xxxxxxurl:jdbc:mysql://mysql:3306/streampark?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true然后在docker-compose-streampark.yml的streampark服务里加挂载,把改好的配置覆盖回容器:
volumes:-/data/streampark/streampark-conf/config.yaml:/streampark/conf/config.yaml重启后报错:
The datasource.dialect is MySQL, but the classes "com.mysql.cj.jdbc.Driver" and "com.mysql.jdbc.Driver" not found. Please ensure that the MySQL Connector/J is located under $streampark/lib. Note: The MySQL Connector/J is not compatible with the Apache 2.0 license.原因:MySQL Connector/J 是 GPL 许可,与 Apache 2.0 不兼容,所以 StreamPark 官方镜像故意不内置MySQL 驱动,需要自己下载放进/streampark/lib/。
下载并挂载:
wget-O/data/streampark/mysql-connector-j-8.0.33.jar\https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.0.33/mysql-connector-j-8.0.33.jarcompose 里加挂载:
volumes:-/data/streampark/mysql-connector-j-8.0.33.jar:/streampark/lib/mysql-connector-j-8.0.33.jar第五步:第三个坑——MySQL 不会自动建表
驱动和连接都好了,重启又报:
java.sql.SQLSyntaxErrorException: Table 'streampark.t_flink_app' doesn't exist原因:StreamPark 对H2(内嵌库)会自动建表,但对MySQL(外部库)不会自动建表,需要手动导入建表脚本。
建表脚本在哪?在容器里:
dockerexecstreamparkfind/streampark-name"*.sql"2>/dev/null# /streampark/script/schema/mysql-schema.sql# /streampark/script/data/mysql-data.sql小技巧:如果 StreamPark 配了 MySQL 但没表,会一直 crash-loop 起不来,
docker exec根本进不去、也拿不到文件。这时可以先注释掉 config.yaml 挂载,让它退回 H2 正常启动,拿到 SQL 文件后再恢复。
导入 SQL(先建表,后插初始数据):
dockercpstreampark:/streampark/script/schema/mysql-schema.sql /data/streampark/mysql-schema.sqldockercpstreampark:/streampark/script/data/mysql-data.sql /data/streampark/mysql-data.sqldockerexec-istreampark-mysql mysql-ustreampark-p'密码'streampark</data/streampark/mysql-schema.sqldockerexec-istreampark-mysql mysql-ustreampark-p'密码'streampark</data/streampark/mysql-data.sql验证:
dockerexecstreampark-mysql mysql-ustreampark-p'密码'streampark-e"SHOW TABLES;"看到一堆t_开头的表,重启 StreamPark,终于正常起来了。
三、根因总结
StreamPark 2.1.5 用 Docker 部署时连不上 MySQL,其实是三个独立的坑叠加:
| # | 坑 | 说明 |
|---|---|---|
| 1 | 配置读 config.yaml,不读环境变量 | SPRING_PROFILES_ACTIVE、MYSQL_*、SPRING_DATASOURCE_*、JAVA_TOOL_OPTIONS全都无效,只有/streampark/conf/config.yaml的datasource.dialect说了算 |
| 2 | 镜像不内置 MySQL 驱动 | GPL 许可与 Apache 2.0 冲突,需自备mysql-connector-j挂进/streampark/lib/ |
| 3 | MySQL 不自动建表 | 只有 H2 内嵌库会自动建表,MySQL 需手动导mysql-schema.sql+mysql-data.sql |
四、完整解决方案(可直接复制)
1. 准备 config.yaml(MySQL 版)
datasource:dialect:mysqlusername:streamparkpassword:你的密码url:jdbc:mysql://mysql:3306/streampark?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true2. 下载 MySQL 驱动
wget-O/data/streampark/mysql-connector-j-8.0.33.jar\https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.0.33/mysql-connector-j-8.0.33.jar3. compose 里挂载(config.yaml + 驱动 + Flink Home)
streampark:image:apache/streampark:2.1.4# 建议 2.1.4,2.1.5 镜像对 MySQL 支持有问题volumes:-/data/streampark/streampark-conf/config.yaml:/streampark/conf/config.yaml-/data/streampark/mysql-connector-j-8.0.33.jar:/streampark/lib/mysql-connector-j-8.0.33.jar-/data/streampark/flink-1.18.1/flink:/opt/flink# 可选:Flink Home4. 导入建表 SQL
dockerexec-istreampark-mysql mysql-ustreampark-p'密码'streampark</data/streampark/mysql-schema.sqldockerexec-istreampark-mysql mysql-ustreampark-p'密码'streampark</data/streampark/mysql-data.sql5. 启动验证
dockercompose-fdocker-compose-streampark.yml up-ddockerexecstreampark-mysql mysql-ustreampark-p'密码'streampark-e"SHOW TABLES;"五、总结
这次排查给我最大的教训是:遇到「配置了却无效」的问题,不要一直往环境变量/启动参数上使劲,先找到这个应用真正读的是哪个配置文件。
StreamPark 的 Docker 镜像有几个「反直觉」的设计:
- 数据库配置在
config.yaml里,环境变量是「障眼法」; - MySQL 驱动要自己放,官方不内置(GPL 许可原因);
- MySQL 要手动建表,不像 H2 那样开箱即用。
希望这篇记录能帮到同样踩坑的人,少走弯路。
附:完整排障命令速查
# 看连的是哪个库dockerlogs streampark2>&1|grep-iE"jdbc:h2|jdbc:mysql|HikariPool"|tail-50# 看真实配置dockerexecstreamparkcat/streampark/conf/config.yaml# 看入口脚本dockerinspect streampark--format'{{json .Config.Entrypoint}}'# 在容器里找 SQL 脚本dockerexecstreamparkfind/streampark-name"*.sql"2>/dev/null# 验证 MySQL 表dockerexecstreampark-mysql mysql-ustreampark-p'密码'streampark-e"SHOW TABLES;"