これは、なにをしたくて書いたもの?
これまでWildFly Maven Pluginをちょいちょいと使ってきているのですが、そういえばこれを使ってコンテナイメージを作ったことがないなと
思いまして。
情報も知らないので、確認がてら試してみることにしました。
wildfly:imageゴール
WildFly Maven Pluginでコンテナイメージを作成するには、wildfly:imageゴールを使います。
WildFly Maven Plugin – wildfly:image
これはWildFly Maven PluginでプロビジョニングしたWildFlyとデプロイメントから、コンテナイメージを作成およびpushするゴールです。
wildfly:imageゴールはpackageゴールを拡張したもので、WildFlyがプロビジョニングされデプロイメントのデプロイ後に
コンテナイメージのビルド、pushが行われます。
The image goal extends the package goal, building and pushing the image occurs after the server is provisioned and the deployment deployed in it.
実行はDockerのバイナリーに依存しているとされています。つまり、実行にはdockerコマンドが必要だということですね。
The image goal relies on a Docker binary to execute all image commands (build, login, push).
これはdockerBinaryというパラメーターでpodmanなどに代替することもできます。
なお、Bootable JARでパッケージングしても無視されるようです。
Note that if a WildFly Bootable JAR is packaged, it is ignored when building the image.
設定のサンプルはこちらです。
WildFly Maven Plugin – Build and push your application in a container image
それでは、簡単なJakarta EEアプリケーションを作成して試してみましょう。
環境
今回の環境はこちら。
$ java --version openjdk 21.0.5 2024-10-15 OpenJDK Runtime Environment (build 21.0.5+11-Ubuntu-1ubuntu124.04) OpenJDK 64-Bit Server VM (build 21.0.5+11-Ubuntu-1ubuntu124.04, mixed mode, sharing) $ mvn --version Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 21.0.5, vendor: Ubuntu, runtime: /usr/lib/jvm/java-21-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "6.8.0-51-generic", arch: "amd64", family: "unix"
アプリケーションを作成する
今回はJakarta RESTful Web Services(以降JAX-RS)を使った簡単なアプリケーションを作成することにします。
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.littlewings</groupId> <artifactId>wildfly-maven-plugin-container-image</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.release>21</maven.compiler.release> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.wildfly.bom</groupId> <artifactId>wildfly-ee-with-tools</artifactId> <version>35.0.0.Final</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>jakarta.ws.rs</groupId> <artifactId>jakarta.ws.rs-api</artifactId> <scope>provided</scope> </dependency> </dependencies> <build> <finalName>ROOT</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.4.0</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> <plugin> <groupId>org.wildfly.plugins</groupId> <artifactId>wildfly-maven-plugin</artifactId> <version>5.1.1.Final</version> <executions> <execution> <goals> <goal>image</goal> </goals> </execution> </executions> <configuration> <overwrite-provisioned-server>true</overwrite-provisioned-server> <discover-provisioning-info> <version>35.0.0.Final</version> </discover-provisioning-info> <!-- あとで --> </configuration> </plugin> </plugins> </build> </project>
WildFly Maven Pluginを追加し、wildfly:imageゴールを実行するように設定しています。これでmvn package時にコンテナイメージを
作成するようになります。
<executions> <execution> <goals> <goal>image</goal> </goals> </execution> </executions>
こちらはWildFly Glowを使うようにしているだけですが、この時点ではこのままいきます。
<configuration> <overwrite-provisioned-server>true</overwrite-provisioned-server> <discover-provisioning-info> <version>35.0.0.Final</version> </discover-provisioning-info> <!-- あとで --> </configuration>
JAX-RSの有効化。
src/main/java/org/littlewings/wildfly/RestApplication.java
package org.littlewings.wildfly; import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.core.Application; @ApplicationPath("/") public class RestApplication extends Application { }
JAX-RSリソースクラス。
src/main/java/org/littlewings/wildfly/HelloResource.java
package org.littlewings.wildfly; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; @Path("/hello") public class HelloResource { @GET @Produces(MediaType.TEXT_PLAIN) public String message() { return "Hello World"; } }
動作確認しておきます。
$ mvn compile wildfly:dev
OKですね。
$ curl localhost:8080/hello Hello World
これで準備は完了です。
WildFly Maven Pluginでコンテナイメージを作成する
では、コンテナイメージを作成しましょう。
以下のように設定しているので
<executions> <execution> <goals> <goal>image</goal> </goals> </execution> </executions>
mvn packageでコンテナイメージが作成できます。
$ mvn package
設定しない場合は、packageに続けてwildfly:imageを実行するとよいでしょう。
$ mvn package wildfly:image
実行すると、途中でこんな表示が出てきました。
[INFO] Generating Dockerfile /path/to/wildfly-maven-plugin-container-image/target/Dockerfile from base image quay.io/wildfly/wildfly-runtime:latest [INFO] Building application image wildfly-maven-plugin-container-image:latest using docker. [INFO] Executing the following command to build application image: 'docker build -t wildfly-maven-plugin-container-image:latest .'
quay.io/wildfly/wildfly-runtime:latestというのがベースイメージのようです。
Dockerfileも作成されるようです。
target/Dockerfile
FROM quay.io/wildfly/wildfly-runtime:latest COPY --chown=jboss:root server $JBOSS_HOME RUN chmod -R ug+rwX $JBOSS_HOME COPY --chown=jboss:root ROOT.war $JBOSS_HOME/standalone/deployments/ROOT.war
コンテナイメージができました。デフォルトのイメージ名はアーティファクト名で、タグはlatestみたいですね。
[INFO] Successfully built application image wildfly-maven-plugin-container-image:latest
実行。
$ docker container run -it --rm -p 8080:8080 wildfly-maven-plugin-container-image:latest
確認。
$ curl localhost:8080/hello Hello World
OKです。
コンテナの中身を見てみる
少しコンテナの中身を見てみましょう。
$ docker container run -it --rm -p 8080:8080 --entrypoint bash wildfly-maven-plugin-container-image:latest
/etc/os-release。
$ cat /etc/os-release NAME="Red Hat Enterprise Linux" VERSION="9.5 (Plow)" ID="rhel" ID_LIKE="fedora" VERSION_ID="9.5" PLATFORM_ID="platform:el9" PRETTY_NAME="Red Hat Enterprise Linux 9.5 (Plow)" ANSI_COLOR="0;31" LOGO="fedora-logo-icon" CPE_NAME="cpe:/o:redhat:enterprise_linux:9::baseos" HOME_URL="https://www.redhat.com/" DOCUMENTATION_URL="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9" BUG_REPORT_URL="https://issues.redhat.com/" REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 9" REDHAT_BUGZILLA_PRODUCT_VERSION=9.5 REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux" REDHAT_SUPPORT_PRODUCT_VERSION="9.5"
Javaは、現時点では21でした。
$ java --version openjdk 21.0.5 2024-10-15 LTS OpenJDK Runtime Environment (Red_Hat-21.0.5.0.11-1) (build 21.0.5+11-LTS) OpenJDK 64-Bit Server VM (Red_Hat-21.0.5.0.11-1) (build 21.0.5+11-LTS, mixed mode, sharing)
設定を変更してみる
ここからは少しWildFly Maven Pluginの設定を変えてみます。
イメージ名とタグを指定してみましょう。image-nameとtagで指定できます。
<configuration> <overwrite-provisioned-server>true</overwrite-provisioned-server> <discover-provisioning-info> <version>35.0.0.Final</version> </discover-provisioning-info> <image-name>my-image</image-name> <tag>0.0.1</tag> </configuration>
パッケージング。
$ mvn package
このようになりました。
[INFO] Successfully built application image my-image:0.0.1
JDKのバージョンを指定する
jdk-versionでJDKのバージョンを指定できます。今回は21を指定。
<configuration> <overwrite-provisioned-server>true</overwrite-provisioned-server> <discover-provisioning-info> <version>35.0.0.Final</version> </discover-provisioning-info> <jdk-version>21</jdk-version> </configuration>
パッケージング。
$ mvn package
途中の様子。
[INFO] Generating Dockerfile /path/to/wildfly-maven-plugin-container-image/target/Dockerfile from base image quay.io/wildfly/wildfly-runtime:latest-jdk21 [INFO] Building application image wildfly-maven-plugin-container-image:latest using docker. [INFO] Executing the following command to build application image: 'docker build -t wildfly-maven-plugin-container-image:latest .'
ベースイメージがquay.io/wildfly/wildfly-runtime:latest-jdk21になりました。
その他
実際に使う時はこんなところでしょうか。
<configuration> <overwrite-provisioned-server>true</overwrite-provisioned-server> <discover-provisioning-info> <version>35.0.0.Final</version> </discover-provisioning-info> <image-name>${project.artifactId}</image-name> <tag>${project.version}</tag> <jdk-version>21</jdk-version> </configuration>
レジストリーにpushする場合は、pushをtrueにして、レジストリーを指定する場合はregistryを指定するようです。
<configuration> <overwrite-provisioned-server>true</overwrite-provisioned-server> <discover-provisioning-info> <version>35.0.0.Final</version> </discover-provisioning-info> <push>true</push> <registry>my-registry</registry> </configuration>
registryを設定した場合、イメージ名にレジストリー名が入るようです。
ベースイメージについて
設定を見ていたのですが、ベースイメージは変更できないようです。
以下で固定されているようですね。
先ほど少し中身を見ましたが、これはUBIのようです。
そしてjdk-versionを指定した時には、quay.io/wildfly/wildfly-runtime:latest-${jdk-version}がベースイメージになります。
現時点では、11、17、21が指定できるようですね。パッチバージョンまで指定できてもいいと思うのですが…latest-の部分は変えられませんね。
このイメージのことは、「UBI9 runtime image」として紹介されています。
New WildFly S2I and Runtime Multi-arch Images
WildFly S2I (Source to Image) builder and runtime images documentation
「wildfly-runtime」という名前なので最初はどういう存在なのかよくわからなかったのですが、WildFlyはあくまでプロビジョニングしたものを
使用し、こちらはUBIとOpenJDKが含まれたイメージだということですね。
wildfly-runtime自体の定義については、こちらを見るとよいと思います。
ベースイメージはregistry.access.redhat.com/ubi9/ubi-minimalのようです。
https://github.com/wildfly/wildfly-s2i/blob/main/wildfly-runtime-image/image.yaml
おわりに
WildFly Maven Pluginでコンテナイメージを作成してみました。
コンテナイメージの作成自体は簡単でしたが、使われているベースイメージがよくわからなかったのでいろいろ調べたりしてみました。
だいたい内容はわかったので、今後WildFlyでコンテナイメージを作る場合には使っていきましょう。