QuarkusプロジェクトにSpring Boot アプリの実装を取り込んだデモプロジェクトでいろいろ実験してみた。
QuarkusのSpringインテグレーション機能
Quarkus - Quarkus Extension for Spring DI API
この辺を注意するといいのかもしれません。
インテグレーション機能と考えるより、移行機能と考えるのがいいかもしれない。
- エントリポイントは不要
@SpringBootApplication
のクラスは削除する
- アプリケーションコンテキストの代替品はありません
- おそらくCDIのコンテキストへ読み替えて実現しているため
- したがって Spring Test で実装したテストコードは移行できない……(ちゃんと調べてないから分からないけど)
- Spring Frameworkのライブラリに対応するQuarkusプラグインが、それぞれのアノテーションをQuarkusのコンテキストへ変換している
プロジェクトの生成
Mavenコマンドで生成します。
mvn io.quarkus:quarkus-maven-plugin:1.12.2.Final:create \ -DprojectGroupId=com.example \ -DprojectArtifactId=spring-data-jpa-web-security-demo \ -DclassName="com.example.demo.GreetingController" \ -Dpath="/greeting" \ -Dextensions="resteasy,spring-web,spring-data-jpa,spring-security,quarkus-elytron-security-properties-file,resteasy-jackson,quarkus-jdbc-h2"
ネイティブ実行可能ファイルの作成
Quarkus - Building a Native Executable
native
プロファイルでpackage
フェーズを実行するとネイティブの実行可能ファイルを作成します。
実行可能ファイルはtarget/spring-data-jpa-web-security-demo-1.0.0-SNAPSHOT-runner
に作成します。
AOTコンパイルに時間がかかるのは変わらないのですが、フレームワーク自体がSpring Bootに比べて小さいため、ビルドマシンに要求するリソースは比較的低くなります。
./mvnw package -Pnative
コンテナイメージの作成
コンテナイメージの作成方法が2種類あります。
- Javaアプリケーションとしてコンテナイメージを作成
- ネイティブ実行可能ファイルからコンテナイメージを作成
Javaアプリケーションとしてコンテナイメージを作成
Jibでコンテナイメージを作成するときはプロファイルにbuild-java-jib
を指定します。
mvn package -Pbuild-java-jib
src/main/docker/Dockerfile.jvm
に従ってコンテナイメージを作成するときはプロファイルにbuild-java-docker
を指定します。
mvn package -Pbuild-java-docker
作成したイメージの大きさはこれぐらいになります。ベースイメージが UBI になるため、比較的大きめ。
$ docker images com.example/spring-data-jpa-web-security-demo REPOSITORY TAG IMAGE ID CREATED SIZE com.example/spring-data-jpa-web-security-demo java-docker 93303798e24f 14 minutes ago 406MB com.example/spring-data-jpa-web-security-demo java-jib bb8fd47095f3 15 minutes ago 225MB
ネイティブ実行可能ファイルからコンテナイメージを作成
Jibでコンテナイメージを作成するときはプロファイルにnative,build-navive-jib
を指定します。
mvn package -Pnative,build-navive-jib
src/main/docker/Dockerfile.native
に従ってコンテナイメージを作成するときはプロファイルにnative,build-navive-docker
を指定します。
mvn package -Pnative,build-navive-docker
src/main/docker/Dockerfile.native-distroless
に従ってコンテナイメージを作成するときはプロファイルにnative,build-navive-distroless
を指定します。
mvn package -Pnative,build-navive-distroless
作成したイメージの大きさはこれぐらいになります。
QuarkusのJibプラグインはベースイメージとしてregistry.access.redhat.com/ubi8/ubi-minimal
(103MB)を利用するため、Dockerfileでdistrolessを使う場合に比べると少し大きくなってしまうのが分かります。
$ docker images com.example/spring-data-jpa-web-security-demo REPOSITORY TAG IMAGE ID CREATED SIZE com.example/spring-data-jpa-web-security-demo native-distroless 618ac1277742 7 seconds ago 87.3MB com.example/spring-data-jpa-web-security-demo native-docker eae04a98e2d0 4 minutes ago 171MB com.example/spring-data-jpa-web-security-demo native-jib 232110e84e33 9 minutes ago 171MB
動作確認してみる。だいたいよさそうだ。
$ docker run --rm -i -p 8080:8080 com.example/spring-data-jpa-web-security-demo:java-jib __ ____ __ _____ ___ __ ____ ______ --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ --\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 2021-03-15 08:18:09,374 INFO [io.agr.pool] (main) Datasource '<default>': Initial size smaller than min. Connections will be created when necessary 2021-03-15 08:18:10,221 INFO [io.quarkus] (main) spring-data-jpa-web-security-demo 1.0.0-SNAPSHOT on JVM (powered by Quarkus 1.12.2.Final) started in 2.235s. Listening on: http://0.0.0.0:8080 2021-03-15 08:18:10,222 INFO [io.quarkus] (main) Profile prod activated. 2021-03-15 08:18:10,222 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-h2, mutiny, narayana-jta, resteasy, resteasy-jackson, security, security-properties-file, smallrye-context-propagation, spring-data-jpa, spring-di, spring-security, spring-web] --- $ curl --user test:test -s localhost:8080/books; echo [] $ curl --user test:test --request POST --header 'Content-Type: application/json' -d '{"title":"test 001"}' -s localhost:8080/book; echo {"id":1,"title":"test 001"} $ curl --user test:test --request POST --header 'Content-Type: application/json' -d '{"title":"test 002"}' -s localhost:8080/book; echo {"id":2,"title":"test 002"} $ curl --user test:test -s localhost:8080/books; echo [{"id":1,"title":"test 001"},{"id":2,"title":"test 002"}] $ curl --user test:test --request PUT --header 'Content-Type: application/json' -d '{"title":"test 001u1"}' -s localhost:8080/book?id=1; echo {"id":1,"title":"test 001u1"} $ curl --user test:test --request DELETE -s localhost:8080/book?id=2; echo 2 $ curl --user test:test -s localhost:8080/books; echo [{"id":1,"title":"test 001u1"}] $ curl -s localhost:8080/books; echo