ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

StreamPark-2.1.5-MySQL踩坑与解决

StreamPark-2.1.5-MySQL踩坑与解决

记一次 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 能正常打开、也能登录,一切都「看起来」正常。直到有一天:

  1. 我改了 compose 配置(加了个 Flink Home 挂载),docker stop后docker compose up -d重启;
  2. 重启后发现之前配置的 team(团队)全没了;
  3. 连进 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.jar

compose 里加挂载:

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/
3MySQL 不自动建表只有 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=true

2. 下载 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.jar

3. 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 Home

4. 导入建表 SQL

dockerexec-istreampark-mysql mysql-ustreampark-p'密码'streampark</data/streampark/mysql-schema.sqldockerexec-istreampark-mysql mysql-ustreampark-p'密码'streampark</data/streampark/mysql-data.sql

5. 启动验证

dockercompose-fdocker-compose-streampark.yml up-ddockerexecstreampark-mysql mysql-ustreampark-p'密码'streampark-e"SHOW TABLES;"

五、总结

这次排查给我最大的教训是:遇到「配置了却无效」的问题,不要一直往环境变量/启动参数上使劲,先找到这个应用真正读的是哪个配置文件。

StreamPark 的 Docker 镜像有几个「反直觉」的设计:

  1. 数据库配置在config.yaml里,环境变量是「障眼法」;
  2. MySQL 驱动要自己放,官方不内置(GPL 许可原因);
  3. 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;"
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进