- はじめに
- Project Starter
- アプリケーションの起動
- プロジェクトの構成
- ネイティブ・ビルド
- ネイティブバイナリの実行
- JVM モードのコンテナ作成
- RestAssured によるテスト
- まとめ
はじめに
クラウドネイティブなアプリケーションフレームワークである Quarkus の バージョン 1.0 リリースが間近ですが2019年11月25日にリリースされました。
現在(2019年11月20日時点)は 1.0.0.CR1 が出ている状況です(と思った矢先に 1.0.0.CR2 が出た模様ですね)。
1.0 リリース記念として Quarkus の Project Starter の使い方と Gradle での実行について見ていきます。
「Quarkus とは」については以下を参照してください。
Project Starter
Quarkus は、以下のページでオプション選択することで、プロジェクトのひな形が入手できます。
Quarkus - Start coding with code.quarkus.io
早速プロジェクトを入手していきましょう。
(1) で Build Tool を選択します。Maven と Gradle が選択できます。
Gradle の方は Preview となっており、まだ完全ではありませんが、ここでは Gradle を選択します。
(2) では拡張機能を選択します。ここでは RESTEasy JAX-RS を選択します。
その他にも多数の Extension が用意されています。
(3) で以下の画面になりプロジェクトの zip ファイルダウンロードできます。
プロジェクトを解答すると以下のような構成になっています。
アプリケーションの起動
まずはそのままアプリケーションを起動してみましょう。
quarkusDev
とすると開発モードでアプリケーショが起動します。
$ ./gradlew quarkusDev
http://localhost:8080
にアクセスすると以下のページが表示されます。
これはプロジェクト内の index.html
が表示されているだけです。
http://localhost:8080/hello
にアクセスすると以下の表示になります。
これは、以下の org.acme.ExampleResource.java
で処理されたものです。
package org.acme; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("/hello") public class ExampleResource { @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return "hello"; } }
単純に hello を返しているだけですね。
プロジェクトの構成
まずは、build.gradle
を見てみましょう。
// this block is necessary to make enforcedPlatform work for Quarkus plugin available // only locally (snapshot) that is also importing the Quarkus BOM buildscript { repositories { mavenLocal() } dependencies { classpath "io.quarkus:quarkus-gradle-plugin:${quarkusPluginVersion}" } } plugins { id 'java' } apply plugin: 'io.quarkus' repositories { mavenLocal() mavenCentral() } dependencies { implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") implementation 'io.quarkus:quarkus-resteasy' testImplementation 'io.quarkus:quarkus-junit5' testImplementation 'io.rest-assured:rest-assured' nativeTestImplementation 'io.quarkus:quarkus-junit5' nativeTestImplementation 'io.rest-assured:rest-assured' } group 'org.acme' version '1.0.0-SNAPSHOT' compileJava { options.compilerArgs << '-parameters' } java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 }
ついでに gradle.properties
も載せておきます。
quarkusPluginVersion=1.0.0.Final quarkusPlatformArtifactId=quarkus-universe-bom quarkusPlatformVersion=1.0.0.Final quarkusPlatformGroupId=io.quarkus
Gradle プラグインとして quarkus-gradle-plugin
を使っています。
プロジェクト作成時のオプションとして RESTEasy JAX-RS を選択したため、依存に quarkus-resteasy
が追加されています。
オプションとして選択したものに応じて、各種依存が定義されたプロジェクトが作成されます。
build.gradle
では 古い Gradle でプラグインを適用する定義になっています。
新しい Gradle では以下のように書くこともできます。
plugins { id 'java' id 'io.quarkus' version '1.0.0.CR1' }
ただし、1.0.0 版では、quarkus-gradle-plugin
の不具合で新しい書き方では動きませんので注意してください。
ネイティブ・ビルド
Quarkus では、GraalVM を使ったネイティブバイナリを作成することができます。
ローカルに GraalVM が入っていれば(環境変数 GRAALVM_HOME が定義されていれば)、直接バイナリをビルドすることもできますが、ここでは Docker 上でビルドしてみましょう。
Docker でビルドする場合は --docker-build
オプションを指定してビルドします(Dockerはインストール済みとします)。
$ ./gradlew buildNative --docker-build=true
ビルドには少々時間がかかりますが、完了すれば build
ディレクトリに code-with-quarkus-1.0.0-SNAPSHOT-runner
というバイナリが作成されます。
ネイティブバイナリの実行
ビルドしたネィティブバイナリはLinux 用なので、実行も Docker で行います。
最初に、少し準備が必要です。
Gradle 用のプロジェクトは Preview 版ということもあってか、Maven 用の設定になっている箇所がいくつかあります。
src/main/docker/Dockerfile.native
は以下のようになっています。
FROM registry.access.redhat.com/ubi8/ubi-minimal WORKDIR /work/ COPY target/*-runner /work/application RUN chmod 775 /work EXPOSE 8080 CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
target
は Maven 用なので build
に変更します。
2019/11/25 追記:1.0.0.Final ではこの問題は修正済みです。
COPY build/*-runner /work/application
なお、編集時に Windows の場合は改行コードが CRLF に変わらないように注意してください。
さらにプロジェクトのルートにある .dockerignore
が以下のようになっています。
2019/11/25 追記:1.0.0.Final ではこの問題は修正済みです。
* !target/*-runner !target/*-runner.jar !target/lib/*
.dockerignore
は docker build 時にビルドコンテキスト(通常はコマンドを叩いたカレントディレクトリ)配下のファイルをサブフォルダも合わせて Docker デーモンにファイルを送信する際に、対象外とするファイルを指定するものです。
以下のように変更します。
* !build/*-runner !build/*-runner.jar !build/lib/*
これで docker build の準備ができました。プロジェクトのルードディレクトリにて docker build しましょう。
$ docker build -f src/main/docker/Dockerfile.native -t quarkus/code-with-quarkus .
-f
で Dockerfile の場所を指定、-t
でタグ名を指定、末尾の .
でカレントディレクトリをビルドコンテキストに指定しています。
以下のような出力と共に、Docker コンテナが作成されます。
Sending build context to Docker daemon 31.29MB Step 1/6 : FROM registry.access.redhat.com/ubi8/ubi-minimal ---> 469119976c56 Step 2/6 : WORKDIR /work/ ---> Using cache ---> 14cb18a3903d Step 3/6 : COPY build/code-with-quarkus-1.0.0-SNAPSHOT-runner /work/application ---> 244714077ecf Step 4/6 : RUN chmod 775 /work ---> Running in b9db39c49807 Removing intermediate container b9db39c49807 ---> 376a646a0478 Step 5/6 : EXPOSE 8080 ---> Running in c6f6d7fd8c70 Removing intermediate container c6f6d7fd8c70 ---> ff2ab5fb1953 Step 6/6 : CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] ---> Running in 57917c5b1593 Removing intermediate container 57917c5b1593 ---> cb723c9e7750 Successfully built cb723c9e7750 Successfully tagged quarkus/code-with-quarkus:latest
コンテナが作成されたら、早速 起動しましょう。
$ docker run -i --rm -p 8080:8080 quarkus/code-with-quarkus
以下のように秒以下で起動します。
2019-11-20 10:42:30,921 INFO [io.quarkus] (main) code-with-quarkus 1.0.0-SNAPSHOT (running on Quarkus 1.0.0.CR1) started in 0.006s. Listening on: http://0.0.0.0:8080 2019-11-20 10:42:30,921 INFO [io.quarkus] (main) Profile prod activated. 2019-11-20 10:42:30,921 INFO [io.quarkus] (main) Installed features: [cdi, resteasy]
http://localhost:8080/hello
にアクセスすると以下の表示になり、起動していることが分かります。
JVM モードのコンテナ作成
先ほどはネィティブバイナリを使ってコンテナ起動しましたが、jar を直接起動するコンテナも簡単に作成できます。
jar を以下で作成します。
$ ./gradlew quarkusBuild
build
ディレクトリに code-with-quarkus-1.0.0-SNAPSHOT-runner.jar
が作成されます。
では、先ほどと同じ流れで docker build しましょう。
JVM モード用の Dockerfile は src/main/docker/Dockerfile.jvm
に用意されています。
こちらも先ほどと同じく target
-> build
に変更して以下のようになります
FROM fabric8/java-alpine-openjdk8-jre ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" ENV AB_ENABLED=jmx_exporter COPY build/lib/* /deployments/lib/ COPY build/*-runner.jar /deployments/app.jar EXPOSE 8080 # run with user 1001 and be prepared for be running in OpenShift too RUN adduser -G root --no-create-home --disabled-password 1001 \ && chown -R 1001 /deployments \ && chmod -R "g+rwX" /deployments \ && chown -R 1001:root /deployments USER 1001 ENTRYPOINT [ "/deployments/run-java.sh" ]
$ docker build -f src/main/docker/Dockerfile.jvm -t quarkus/code-with-quarkus-jvm .
以下のようにコンテナが作成されます。
Sending build context to Docker daemon 31.29MB Step 1/9 : FROM fabric8/java-alpine-openjdk8-jre ---> 6383f0513235 Step 2/9 : ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" ---> Using cache ---> e2e8ca4359b6 Step 3/9 : ENV AB_ENABLED=jmx_exporter ---> Using cache ---> c73944d90c45 Step 4/9 : COPY build/lib/* /deployments/lib/ ---> 06772c22ad5c Step 5/9 : COPY build/*-runner.jar /deployments/app.jar ---> c91141d2157f Step 6/9 : EXPOSE 8080 ---> Running in 12b3b2e73ca1 Removing intermediate container 12b3b2e73ca1 ---> de4f26ce38bb Step 7/9 : RUN adduser -G root --no-create-home --disabled-password 1001 && chown -R 1001 /deployments && chmod -R "g+rwX" /deployments && chown -R 1001:root /deployments ---> Running in c218022a1ad8 Removing intermediate container c218022a1ad8 ---> 368b377a51e2 Step 8/9 : USER 1001 ---> Running in b822230b842b Removing intermediate container b822230b842b ---> b0b9a5bfa94a Step 9/9 : ENTRYPOINT [ "/deployments/run-java.sh" ] ---> Running in a31d01fdab46 Removing intermediate container a31d01fdab46 ---> 5295a11b2e32 Successfully built 5295a11b2e32 Successfully tagged quarkus/code-with-quarkus-jvm:latest
実行は以下のコマンドで行います。
$ docker run -i --rm -p 8080:8080 quarkus/code-with-quarkus-jvm
ネイティブ版には敵いませんが、2秒程度で起動します。
http://localhost:8080/hello
にアクセスすると以下の表示になり、起動していることが分かります。
最後に、ここで起動したアプリケーションに対してテストを行いましょう。
RestAssured によるテスト
RestAssured によるテストのひな形は ExampleResourceTest.java
として用意されています。
package org.acme; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; import static io.restassured.RestAssured.given; import static org.hamcrest.CoreMatchers.is; @QuarkusTest public class ExampleResourceTest { @Test public void testHelloEndpoint() { given() .when().get("/hello") .then() .statusCode(200) .body(is("hello")); } }
テストは以下のコマンドで行います。
$ ./gradlew test
起動中のアプリケーションに対してテストが行われ、build/reports/tests/test/index.html
に以下のようなレポートが作成されます。
まとめ
Quarkus の プロジェクト作成からコンテナによる実行までを見てきました。
Maven 優先で開発されており、Gradle サポートは Preview 扱いなので、躓く点も多少ありますが、一通りの動作は確認できました。
その他機能についても追って見ていきたいと思います。
Kubernetes完全ガイド (impress top gear)
- 作者:青山 真也
- 出版社/メーカー: インプレス
- 発売日: 2018/09/21
- メディア: 単行本(ソフトカバー)
- 作者:Sam Newman
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/02/26
- メディア: 単行本(ソフトカバー)