Docker镜像classpath下无法识别自定义LiquibaseDataTypes问题求助
排查方向与修复步骤
SPI声明文件完整性校验
自定义DataType通过SPI注册的核心前提是jar包内包含正确的服务声明文件。很多场景下集成在应用内运行正常,是因为应用打包插件(如Spring Boot maven插件)会自动合并SPI文件,单独构建schema-impl.jar时容易遗漏资源拷贝。
校验方法:解压本地构建的schema-impl.jar,检查META-INF/services/liquibase.datatype.LiquibaseDatatype文件是否存在,文件内是否逐行列出所有自定义DataType的全限定类名,无多余空格、空行或类名拼写错误。如果文件缺失,在pom.xml中配置maven资源插件,确保src/main/resources下的文件全部被打入jar包。Classpath加载顺序修正
Liquibase 4.3.5版本的类加载器不会自动扫描classpath目录下嵌套jar包的SPI声明,必须在classpath配置中显式指定jar包路径,且放在高优先级位置。当前配置同时声明了目录和目录下jar,目录优先级高于jar会导致jar内SPI不被扫描。
将liquibase.docker.properties中的classpath配置修改为:classpath: /liquibase/classpath/schema-impl.jar:/liquibase/changelog:/liquibase/classpath liquibase.headless: true启动容器时追加
--log-level=FINE参数,从启动日志中确认schema-impl.jar确实被加入加载列表,无路径覆盖问题。类冲突问题排查
如果schema-impl.jar被打成了包含Liquibase核心依赖的fat jar,会触发类加载器隔离问题:SPI扫描到自定义类型类文件,但加载时匹配的是jar包内自带的Liquibase核心类,和镜像内置的4.3.5版本核心类不兼容,最终导致类型注册失败。
校验方法:解压schema-impl.jar,检查是否存在liquibase/开头的类路径,如果存在,修改打包插件配置,排除所有liquibase.*相关的传递依赖,仅保留自定义业务类与SPI声明文件即可。Docker构建缓存校验
若之前构建镜像时复制过不含SPI声明的旧版schema-impl.jar,Docker层缓存可能导致容器内的文件未更新为最新版本。
校验方法:启动临时交互容器,执行ls -l /liquibase/classpath/schema-impl.jar核对文件大小、修改时间与本地最新构建的jar一致,也可直接在容器内解压该jar核查SPI文件内容。构建镜像时可追加--no-cache参数排除缓存干扰。
快速验证方法
无需执行全量changeset,在容器内执行以下命令即可验证自定义类型是否加载成功:
liquibase --classpath=/liquibase/classpath/schema-impl.jar data-type list
如果输出的类型列表中存在定义的my-string类型,说明扩展加载正常,再执行迁移任务就不会报类型不存在的错误。
内容的提问来源于stack exchange,提问作者Rafa S.R.

