Ponz Dev Log

ゆるくてマイペースな開発日記

TomcatアプリケーションをS2Iでコンテナ化してOpenShiftで動かす

Tomcatで動作するJavaアプリケーションをS2Iでコンテナ化してOpenShiftで動作させる方法の備忘録です。 手元にTomcatアプリケーションはあるけど、コンテナ化やOpenShift/k8sの設定が面倒だなというモチベーションで調査した結果を書き残します。

環境情報

コンポーネント バージョン
JDK 11
Tomcat 9.0.x (*1)
OpenShift 4.12.0 (*2)

アプリケーションの準備

この記事ではコンテナ化してOpenShift上で動作させることを最速で実現するため、 mvn archetype:generate で生成したシンプルなServlet/JSPアプリケーションを題材とします。

$ mvn archetype:generate \
    -DarchetypeGroupId=org.apache.maven.archetypes \
    -DarchetypeArtifactId=maven-archetype-webapp \
    -DarchetypeVersion=1.4 \
    -DgroupId=com.example \
    -DartifactId=jws-sample-webapp \
    -Dversion=1.0.0 \
    -DinteractiveMode=false

$ cd jws-sample-webapp

$ tree .
.
├── pom.xml
└── src
    └── main
        └── webapp
            ├── WEB-INF
            │   └── web.xml
            └── index.jsp

手元のJDKのバージョンと合わせるため、pom.xmlではJavaバージョンを1.7から11に変更します。

<project ...>
  <properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <!-- 他は変更せず -->
</project>

S2Iでコンテナ化する前に、MavenコマンドでWARファイルを生成できることを確認しておきます。

$ mvn clean package -DskipTests -B -ntp
[INFO] Scanning for projects...
...
[INFO] BUILD SUCCESS

$ ls target/*.war
target/jws-sample-webapp.war

S2IでTomcatアプリケーションをコンテナ化

それでは手元のソースコードをS2IでTomcatアプリケーションでコンテナ化します。 OpenShift CLIの操作例をいくつか例示しますが、 oc login コマンドでOpenShiftにログイン済みの状態を前提とします。

ビルダーイメージの選択

OpenShiftではTomcatアプリケーションをコンテナ化するビルダーイメージが用意されています。 openshift プロジェクトのImageStreamから最新のビルダーイメージを検索します。 本記事執筆時点で最新のImageStreamTagであるJBoss Web Server 5.6.2を使用します。

$ # JWSのImageStreamを検索
$ oc get is -n openshift | grep '^jboss-webserver' | cut -d ' ' -f 1 | grep 'openjdk11'
jboss-webserver53-openjdk11-tomcat9-openshift
jboss-webserver54-openjdk11-tomcat9-openshift-rhel7
jboss-webserver54-openjdk11-tomcat9-openshift-ubi8
jboss-webserver56-openjdk11-tomcat9-openshift-ubi8  # これを使う

$ # JWS 5.6のImageStreamからImageStreamTagを検索
$ oc get istag -n openshift | grep 'jboss-webserver56-openjdk11-tomcat9-openshift-ubi8'  | cut -d ' ' -f 1
jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:5.6.0
jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:5.6.1
jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:5.6.2  # これを使う
jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:latest

S2Iによるコンテナイメージのビルド

oc コマンドでBuildConfigリソースを作成し、先ほど検索したImageStreamTagを指定します。 Dockerfileを使わずソースコードからコンテナイメージを作成するため、バイナリビルドのフラグ --binary=true をコマンドに付与します。

$ oc new-build --name=tomcat-sample-app \
  --image-stream=jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:5.6.2 \
  --binary=true 
--> Found image af8501c (4 months old) in image stream "openshift/jboss-webserver56-openjdk11-tomcat9-openshift-ubi8" under tag "5.6.2" for "jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:5.6.2"

    JBoss Web Server 5.6 OpenJDK11 
    ------------------------------ 
    Platform for building and running web applications on JBoss Web Server 5.6 with OpenJDK11 - Tomcat v9

    Tags: builder, java, tomcat9

    * A source build using binary input will be created
      * The resulting image will be pushed to image stream tag "tomcat-sample-app:latest"
      * A binary build was created, use 'oc start-build --from-dir' to trigger a new build

--> Creating resources with label build=tomcat-sample-app ...
    imagestream.image.openshift.io "tomcat-sample-app" created
    buildconfig.build.openshift.io "tomcat-sample-app" created
--> Success

BuildConfigリソースの作成に成功したら、ソースコードディレクトリを指定してS2Iを実行します。 ビルダーイメージ内のS2Iスクリプトが実行され、コンテナイメージ生成のログが出力されます。 Push successful と表示されたらコンテナイメージのビルドは成功です。 コンテナイメージはOpenShiftの内部レジストリに格納されます。

$ oc start-build tomcat-sample-app --from-dir=. --follow
Uploading directory "." as binary input for the build ...
(...omit...)
Push successful

アプリケーションのデプロイ

コンテナイメージのビルドが無事完了したら、いよいよOpenShiftにアプリケーションをデプロイ (=コンテナを起動) します。 oc new-app コマンドで先ほどビルドしたコンテナイメージ名を指定してデプロイします。 ビルダーイメージからビルドしたTomcat (JWS) アプリケーションは、環境変数 ENABLE_ACCESS_LOG を指定することでアクセスログを出力する Access Log Valve が有効化されます。

$ oc new-app tomcat-sample-app --env=ENABLE_ACCESS_LOG=true
...
--> Creating resources ...
    deployment.apps "tomcat-sample-app" created
    service "tomcat-sample-app" created
--> Success

出力されたログから、コンテナを起動するDeploymentリソースとServiceリソースが作成されていることがわかります。 OpenShift Webコンソールのトポロジービューで参照すると、Deployment管理下のPodがRunningステータスで実行されているはずです。 (スクリーンショットで表示されているヘルスチェックの設定は別記事で取り上げる予定)

さらに外部からもアクセスできるようにRouteリソースも追加で作成します。 oc get route で外部からアクセス可能なホスト名を取得できます。

$ oc expose svc/tomcat-sample-app

$ oc get route tomcat-sample-app -o jsonpath='{.spec.host}'
<サンプルアプリのホスト名>

http://<ホスト名>/jws-sample-webappWebブラウザでアクセスするとJSPのページが表示されます。 ホスト名以降のパス (コンテキストルート) はデフォルトでWARファイル名です。

Podのログを参照するとTomcatJavaのバージョン、そしてアクセスログが出力されています。

$ oc logs tomcat-sample-app-aaaaaa
...
Server version name: Apache Tomcat/9.0.50.redhat-00007
JVM Version: 11.0.16+8-LTS
JVM Vendor: Red Hat, Inc.
CATALINA_BASE: /opt/jws-5.6/tomcat
CATALINA_HOME: /opt/jws-5.6/tomcat
...
<接続元IPアドレス> - - [20/Jan/2023:04:56:27 +0000] <ホスト名> "GET /jws-sample-webapp/ HTTP/1.1" 200 52

参考


以上。