はじめに
QUARKUS触ってみたいなーと前々から思っていたので、KotlinとGradleを使ったQUARKUSのサンプルを作ってみました
QUARKUSのドキュメントではmavenのほうが情報が厚そうだったのですが、pom.xml書きたくない、スクリプトで依存性管理したいと思ったのでGradleを選択しました
とりあえず今回はネイティブイメージをビルドするところまでです
また、自分はmacを使っているのでmacユーザー向けに書いていきます
作成したコードのリポジトリはこちらになります
https://github.com/yoshi10321/sample-quarkus-app
GraalVMのインストール
まずGraalVMをインストールします
https://github.com/oracle/graal/releases
macの場合
graalvm-ce-darwin-amd64-{バージョン名}.tar.gz
というファイルをダンロードして解凍します
解凍したディレクトリを
/Library/Java/JavaVirtualMachines
に移動しておきます
/usr/libexec/java_home -V
コマンドを叩くとインストールしてあるJavaのバージョンが見れます
GraalVMがあればOK
環境変数にセットしてGraalVMを使うようにします
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
export PATH=$JAVA_HOME/bin:$PATH
次にネイティブイメージ作成用にnative-image
ツールをインストールしておきます
gu install native-image
ここまでやったらGraalVMのインストールは完了です
Gradleプロジェクトの作成
mavenだと便利なQUAKUSプロジェクト作成用のコマンドが用意されているようですが、現状Gradleではまだそういった便利なものは用意されてなかったので自分で作っていきます
まず好きなディレクトリを作成してそこに移動しておきます
mkdir sample-quarkus-app
cd sample-quarkus-app
下記のコマンドでgradleのkotlinプロジェクトが作成できます
gradle init --type=kotlin-application
QUARKUSの設定を追加していく
まずQUARKUSのGradle pluginがまだGradle Plugin Portalに上がってないから./settings.gradle.kts
に下記のコードを追加します
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == "io.quarkus") {
useModule("io.quarkus:quarkus-gradle-plugin:${requested.version}")
}
}
}
}
次にbuild.gradle.kts
の中身はこんな感じになりました
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
plugins {
// Apply the Kotlin JVM plugin to add support for Kotlin on the JVM.
id("org.jetbrains.kotlin.jvm").version("1.3.31")
id("org.jetbrains.kotlin.plugin.allopen") version "1.3.41"
java
id("io.quarkus") version "0.19.1"
}
allOpen {
annotation("javax.ws.rs.Path")
annotation("javax.enterprise.context.ApplicationScoped")
annotation("sample.quarkus.app.MyAnnotation")
}
repositories {
jcenter()
mavenCentral()
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation(enforcedPlatform("io.quarkus:quarkus-bom:0.19.1"))
implementation("io.quarkus:quarkus-resteasy")
implementation("io.quarkus:quarkus-resteasy-jsonb")
implementation("io.quarkus:quarkus-kotlin")
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation("io.quarkus:quarkus-junit5")
testImplementation("io.rest-assured:rest-assured:3.1.0")
}
quarkus {
setSourceDir(project.projectDir.resolve("src/main/kotlin").absolutePath)
setOutputDirectory(project.projectDir.resolve("build/classes/kotlin/main").absolutePath)
}
kotlin.sourceSets["test"].kotlin.srcDirs("test")
build.gradleの設定で自分が少しハマったところを書いておくと
-
sourceDir
を設定しないと./gradlew quarkusDev
で起動した時にエラーが発生します -
implementation("io.quarkus:quarkus-resteasy-jsonb")
これを入れないと
@GET
@Produces(MediaType.APPLICATION_JSON)
fun hello() = Greeting("hello")
このコードのようなjsonフォーマットでレスポンスを返すときのjsonシリアライズでコケました
-
implementation("io.quarkus:quarkus-kotlin")
これを入れないとkotlinで書いたコードのホットリロードがうまく動かなかったです - kotlinのクラスはデフォルトで
final
クラスになってしまうのでallopenプラグインを使ってopenにします。ただなぜかApplicationScopedアノテーションを付けたクラスでうまく効いてくれなかったので、別途手動でopenをつけたりもしました。(原因調べきれてないです、すいません)
下記のコマンドで起動することで、ホットリロードが有効な状態で起動できます
./gradlew quarkusDev
ブラウザでlocalhost:8080/hello
にアクセスするとjsonのレスポンスが返ってくるのが確認できます
Kotlinのコードはgithubの方を参照していただければと思います
https://github.com/yoshi10321/sample-quarkus-app
ネイティブイメージのビルド
環境変数にGRAALVM_HOME
をセットしておく必要があります
macの場合は下記のように設定します
export GRAALVM_HOME=$HOME/Development/graalvm/Contents/Home/
docker向けにネイティブビルドする場合は下記のコマンドを叩きます
./gradlew buildNative --docker-build=true
このときquarkusBuild
タスクの実行中に失敗するかもしれません
自分はsrc/main/resources
の中に設定のpropertiesファイルが無かったのが原因でした
同様の現象が発生した場合はgradleのquarkusタスクにあるgenerateConfig
を実行すると設定ファイルが作成されます
作成後に再度buildNativeをすればうまくいきました
実際にDockerにデプロイしていきます
Dockerfileを作成して
FROM registry.access.redhat.com/ubi8/ubi-minimal
WORKDIR /work/
COPY build/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
下記のコマンドでDocker build&runしていきます
docker build -f Dockerfile -t sample/quarkus-app .
docker run -i --rm -p 8080:8080 sample/quarkus-app
-> % docker run -i --rm -p 8080:8080 sample/quarkus-app
2019-07-21 16:50:38,190 INFO [io.quarkus] (main) Quarkus 0.19.1 started in 0.013s. Listening on: http://0.0.0.0:8080
2019-07-21 16:50:38,191 INFO [io.quarkus] (main) Installed features: [cdi, kotlin, resteasy, resteasy-jsonb]
0.013秒で起動したというログが確認できました。
Kotlinで書いたコードがこの速さで起動するのは感動ものです
終わりに
少しハマったところもありましたがQUARKUSのアプリケーションをKotlinとGradleを使ってネイティブ起動するところまでいけました
ネイティブコードで実行することでJVMの起動が遅い問題が回避できるため、Kubernetes上で起動させたときのオートスケーリング時のパラメータ設定にそこまで気を使わなくても良くなるんじゃないかなということを期待しています
今後も特にQUARKUS, GraalVM周りの情報には期待していきたいですね。