TAPに古いバージョンのSpring Bootを使ったアプリをデプロイする際にいくつか問題が起きるので、回避策をメモします。
今回は https://github.com/making/demo-download-view をデプロイしてみます。
このアプリはSpring Boot 1.3 を使用して、7年前に作成されました。
このアプリをそのままTAPにデプロイしてみましょう。
tanzu apps workload apply demo-download-view \
--app demo-download-view \
--git-repo https://github.com/making/demo-download-view \
--git-branch master \
--type web \
--annotation autoscaling.knative.dev/minScale=1 \
--build-env BP_JVM_VERSION=8 \
-n demo \
-y
発生するエラーを1つ1つ対処していきます。
目次
- Mavenが古いことによるビルドエラー
- Spring-Boot-LibがMANIFEST.MFに存在しないことによるビルドエラー
- Spring-Boot-ClassesがMANIFEST.MFに存在しないことによるビルドエラー
- Spring Cloud Bindingsに関するランタイムエラー
- Tanzu Build Service単体の場合
Mavenが古いことによるビルドエラー
Build Serviceによるイメージ作成時に、まず次のエラーが発生しました。
Compiled Application: Contributing to layer
Executing mvnw --settings=/platform/bindings/settings-xml/settings.xml --batch-mode -Dmaven.test.skip=true --no-transfer-progress package
Downloading https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip
........................................................................................................................................................................................................................................................................................................................................................................................................................
Unzipping /home/cnb/.m2/wrapper/dists/apache-maven-3.3.3-bin/3opbjp6rgl6qp7k2a6tljcpvgp/apache-maven-3.3.3-bin.zip to /home/cnb/.m2/wrapper/dists/apache-maven-3.3.3-bin/3opbjp6rgl6qp7k2a6tljcpvgp
Set executable permissions for: /home/cnb/.m2/wrapper/dists/apache-maven-3.3.3-bin/3opbjp6rgl6qp7k2a6tljcpvgp/apache-maven-3.3.3/bin/mvn
Unable to parse command line options: Unrecognized option: --no-transfer-progress
Maven Buildpackはmavenビルドを実行時に --no-transfer-progress
オプションをつけてログの出力を抑制するのですが、
このオプションはMaven 3.6.1で導入されました。今回のアプリに含まれるMaven WrapperはMavenを3.3.3を使用しており、このオプションが存在しないためにエラーが発生しました。
ソースコードのディレクトリで次のコマンドを実行すると、Maven Wrapperが使用するMavenのバージョンを最新にすることができます。
mvn wrapper:wrapper
次のように特定のバージョンを指定することもできます
mvn wrapper:wrapper -Dmaven=3.8.6
今回は次のコミットでMaven Wrapperを更新しました。
https://github.com/making/demo-download-view/commit/25eac90254d3c728ec1c4b90740aff51495e434c
もしくは次のビルド環境変数を設定し、 --no-transfer-progress
オプションをつけないようにしても良いでしょう。
--build-env BP_MAVEN_BUILD_ARGUMENTS='-Dmaven.test.skip=true package' \
Spring-Boot-LibがMANIFEST.MFに存在しないことによるビルドエラー
Git上のソースコードを更新すると、再度イメージのビルドが実行されます。今度は次のエラーが発生しました。
Paketo Buildpack for Spring Boot 5.19.0
https://github.com/paketo-buildpacks/spring-boot
Build Configuration:
$BP_SPRING_CLOUD_BINDINGS_DISABLED false whether to contribute Spring Boot cloud bindings support
Launch Configuration:
$BPL_SPRING_CLOUD_BINDINGS_DISABLED false whether to auto-configure Spring Boot environment properties from bindings
$BPL_SPRING_CLOUD_BINDINGS_ENABLED true Deprecated - whether to auto-configure Spring Boot environment properties from bindings
Paketo Buildpack for Spring Boot 5.19.0
manifest does not container Spring-Boot-Lib
ERROR: failed to build: exit status 1
jarファイルの中のMANIFEST.MFにSpring-Boot-Lib
がないというエラーです。
次のBuildpackのソースコードを読むと、BuildpackはBOMにdependenciesを追加するためにこの項目に設定されたディレクトリを見ているようです。
このSpring-Boot-Lib
はMavenの場合はSpring Boot 1.4.0、Gradleの場合は2.0.9から含まれたようです。
- https://github.com/spring-projects/spring-boot/issues/5183
- https://github.com/spring-projects/spring-boot/issues/16068
サポートされたバージョンでは次のような値がMANIFEST.MFに設定されます。
- https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/resources/org/springframework/boot/jarmode/layertools/test-manifest.MF#L10 (jarの場合)
- https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/resources/org/springframework/boot/jarmode/layertools/test-war-manifest.MF#L10 (warの場合)
サポートされていないバージョンでは何らかの方法で、MANIFEST.MFにこの値を設定する必要があります。 MANIFST.MFに対してはMavenではmaven-jar-pluginを使って次のように任意の項目を追加できます。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Spring-Boot-Lib>lib/</Spring-Boot-Lib>
</manifestEntries>
</archive>
</configuration>
</plugin>
warファイルを作成している場合はmaven-jar-pluginをmaven-war-pluginに変えてください。 設定すべき内容はSpring Bootのバージョンによって異なります。jarのレイアウトが変わるからです。
jarやwarのレイアウトを確認したい場合はzipinfo
コマンドを使ってください。
$ zipinfo target/demo-0.0.1-SNAPSHOT.jar
Archive: target/demo-0.0.1-SNAPSHOT.jar
Zip file size: 20306425 bytes, number of entries: 122
-rw---- 2.0 fat 0 bX defN 22-Dec-22 11:25 META-INF/
-rw---- 2.0 fat 477 bl defN 22-Dec-22 11:25 META-INF/MANIFEST.MF
drwxr-xr-x 1.0 unx 0 b- stor 22-Dec-22 11:25 templates/
drwxr-xr-x 1.0 unx 0 b- stor 22-Dec-22 11:25 com/
drwxr-xr-x 1.0 unx 0 b- stor 22-Dec-22 11:25 com/example/
-rw-r--r-- 2.0 unx 419 bl defN 22-Dec-22 11:25 templates/index.html
-rw-r--r-- 2.0 unx 15 bl defN 22-Dec-22 11:25 hello.txt
-rw-r--r-- 2.0 unx 730 bl defN 22-Dec-22 11:25 com/example/DemoDownloadViewApplication.class
-rw-r--r-- 2.0 unx 701 bl defN 22-Dec-22 11:25 com/example/HelloForm.class
-rw-r--r-- 2.0 unx 1586 bl defN 22-Dec-22 11:25 com/example/HelloController.class
-rw-r--r-- 2.0 unx 2112 bl defN 22-Dec-22 11:25 com/example/DownloadView.class
-rw-r--r-- 2.0 unx 0 bl defN 22-Dec-22 11:25 application.properties
drwxr-xr-x 1.0 unx 0 b- stor 22-Dec-22 11:25 META-INF/maven/
drwxr-xr-x 1.0 unx 0 b- stor 22-Dec-22 11:25 META-INF/maven/com.example/
drwxr-xr-x 1.0 unx 0 b- stor 22-Dec-22 11:25 META-INF/maven/com.example/demo/
-rw-r--r-- 2.0 unx 1913 bl defN 22-Dec-22 11:24 META-INF/maven/com.example/demo/pom.xml
-rw-r--r-- 2.0 unx 109 bl defN 22-Dec-22 11:25 META-INF/maven/com.example/demo/pom.properties
-rw---- 2.0 fat 0 bl defN 22-Dec-22 11:25 lib/
-rw---- 1.0 fat 193581 b- stor 15-Nov-16 02:45 lib/spring-boot-devtools-1.3.0.RELEASE.jar
-rw---- 1.0 fat 533592 b- stor 15-Nov-16 02:34 lib/spring-boot-1.3.0.RELEASE.jar
...
-rw---- 1.0 fat 1077165 b- stor 15-Nov-15 08:03 lib/spring-core-4.2.3.RELEASE.jar
-rw---- 2.0 fat 0 bl defN 22-Dec-22 11:25 org/
-rw---- 2.0 fat 0 bl defN 22-Dec-22 11:25 org/springframework/
-rw---- 2.0 fat 0 bl defN 22-Dec-22 11:25 org/springframework/boot/
-rw---- 2.0 fat 0 bl defN 22-Dec-22 11:25 org/springframework/boot/loader/
-rw---- 2.0 fat 1257 bl defN 15-Nov-16 02:31 org/springframework/boot/loader/LaunchedURLClassLoader$Java7LockProvider.class
...
-rw---- 2.0 fat 884 bl defN 15-Nov-16 02:31 org/springframework/boot/loader/archive/ExplodedArchive$FileNotFoundURLConnection.class
-rw---- 2.0 fat 192 bl defN 15-Nov-16 02:31 org/springframework/boot/loader/JavaAgentDetector.class
122 files, 20382587 bytes uncompressed, 20285023 bytes compressed: 0.5%
今回は次のコミットでpom.xmlを更新しました。
https://github.com/making/demo-download-view/commit/e13e75a10560721e9f2c86563494bafb94dae8d1
Spring-Boot-ClassesがMANIFEST.MFに存在しないことによるビルドエラー
Git上のソースコードを更新すると、再度イメージのビルドが実行されます。今度は次のエラーが発生しました。
Paketo Buildpack for Spring Boot 5.19.0
https://github.com/paketo-buildpacks/spring-boot
Build Configuration:
$BP_SPRING_CLOUD_BINDINGS_DISABLED false whether to contribute Spring Boot cloud bindings support
Launch Configuration:
$BPL_SPRING_CLOUD_BINDINGS_DISABLED false whether to auto-configure Spring Boot environment properties from bindings
$BPL_SPRING_CLOUD_BINDINGS_ENABLED true Deprecated - whether to auto-configure Spring Boot environment properties from bindings
Paketo Buildpack for Spring Boot 5.19.0
manifest does not contain Spring-Boot-Classes
ERROR: failed to build: exit status 1
先ほどと同様にjarファイルの中のMANIFEST.MFにSpring-Boot-Classes
がないというエラーです。
次のBuildpackのソースコードを読むと、アプリケーションのタイプを検出するためにこの項目に設定されたディレクトリを見ているようです。
サポートされたバージョンでは次のような値がMANIFEST.MFに設定されます。
- https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/resources/org/springframework/boot/jarmode/layertools/test-manifest.MF#L9 (jarの場合)
- https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/resources/org/springframework/boot/jarmode/layertools/test-war-manifest.MF#L9 (warの場合)
今回もmaven-jar-plugin or maven-war-pluginでこの項目を設定します。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Spring-Boot-Lib>lib/</Spring-Boot-Lib>
<Spring-Boot-Classes>.</Spring-Boot-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
今回は次のコミットでpom.xmlを更新しました。
https://github.com/making/demo-download-view/commit/ae127b2bbad58f663573489cbe95f24ff165129e
Spring Cloud Bindingsに関するランタイムエラー
Git上のソースコードを更新すると、再度イメージのビルドが実行されます。今度はイメージのビルドが成功し、アプリの起動が始まりました。 しかし、起動時に次のようなエラーが発生し、アプリは起動しません。
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
at java.lang.Thread.run(Thread.java:750)
Caused by: java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.context.ApplicationListener : org.springframework.cloud.bindings.boot.BindingSpecificEnvironmentPostProcessor
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:396)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:373)
at org.springframework.boot.SpringApplication.initialize(SpringApplication.java:253)
at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:227)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1112)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1101)
at com.example.DemoDownloadViewApplication.main(DemoDownloadViewApplication.java:10)
... 6 more
Caused by: java.lang.ClassNotFoundException: org.springframework.cloud.bindings.boot.BindingSpecificEnvironmentPostProcessor
at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at org.springframework.boot.loader.LaunchedURLClassLoader.doLoadClass(LaunchedURLClassLoader.java:166)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:130)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:250)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:389)
... 12 more
Spring Cloud Bindingsに関連するエラーです。このライブラリはイメージビルド時に自動で追加されるライブラリですが、Spring Bootのバージョンのせいか、ClassNotFoundExceptionが発生してしまいます。
Service Binidngを使わない場合は、Spring Cloud Bindingsはなくても良いので、--build-env BP_SPRING_CLOUD_BINDINGS_DISABLED=true
オプションをつけて、ビルド時にSpring Cloud Bindingsを無効にします。
最終的に実行したコマンドは次です。
tanzu apps workload apply demo-download-view \
--app demo-download-view \
--git-repo https://github.com/making/demo-download-view \
--git-branch tap \
--type web \
--annotation autoscaling.knative.dev/minScale=1 \
--build-env BP_JVM_VERSION=8 \
--build-env BP_SPRING_CLOUD_BINDINGS_DISABLED=true \
-n demo \
-y
$ tanzu apps workload get -n demo demo-download-view
📡 Overview
name: demo-download-view
type: web
💾 Source
type: git
url: https://github.com/making/demo-download-view
branch: tap
📦 Supply Chain
name: source-to-url
RESOURCE READY HEALTHY TIME OUTPUT
source-provider True True 42m GitRepository/demo-download-view
image-provider True True 101s Image/demo-download-view
config-provider True True 12m PodIntent/demo-download-view
app-config True True 12m ConfigMap/demo-download-view
service-bindings True True 12m ConfigMap/demo-download-view-with-claims
api-descriptors True True 12m ConfigMap/demo-download-view-with-api-descriptors
config-writer True True 81s Runnable/demo-download-view-config-writer
🚚 Delivery
name: delivery-basic
RESOURCE READY HEALTHY TIME OUTPUT
source-provider True True 11m ImageRepository/demo-download-view-delivery
deployer True True 69s App/demo-download-view
💬 Messages
No messages found.
🛶 Pods
NAME READY STATUS RESTARTS AGE
demo-download-view-00001-deployment-76b5cc876c-t9clq 0/2 Terminating 7 (5m19s ago) 11m
demo-download-view-00002-deployment-76dbf5f776-z7qvj 2/2 Running 0 71s
demo-download-view-build-1-build-pod 0/1 Init:Error 0 47m
demo-download-view-build-2-build-pod 0/1 Init:Error 0 42m
demo-download-view-build-3-build-pod 0/1 Init:Error 0 26m
demo-download-view-build-4-build-pod 0/1 Init:Error 0 16m
demo-download-view-build-5-build-pod 0/1 Completed 0 14m
demo-download-view-build-6-build-pod 0/1 Completed 0 2m29s
demo-download-view-config-writer-d9l79-pod 0/1 Completed 0 92s
demo-download-view-config-writer-f9kvp-pod 0/1 Completed 0 12m
🚢 Knative Services
NAME READY URL
demo-download-view Ready https://demo-download-view-demo.127-0-0-1.sslip.io
To see logs: "tanzu apps workload tail demo-download-view --namespace demo"
これでアプリが起動し、アプリにアクセできました。
$ curl -k "https://demo-download-view-demo.127-0-0-1.sslip.io/download?fileName=tap"
Hello Download!
Tanzu Build Service単体の場合
Tanzu Build Serviceのみを使用している場合は、次のコマンドが等価です。
kp image save demo-download-view \
--git https://github.com/making/demo-download-view \
--git-revision tap \
--tag ghcr.io/making/demo-download-view \
--env BP_JVM_VERSION=8 \
--env BP_SPRING_CLOUD_BINDINGS_DISABLED=true \
-n demo
古いSpring Bootのバージョンに起因するbuildpackの問題を回避しました。
この回避策を使うのではなく、できればSpring Bootをバージョンアップしてください。