以下のStackを使用したレガシーなJavaアプリをTanzu Application Platform (TAP) 1.7にデプロイしてみます。
- Apache Struts 1.2.x
- iBatis 2.3.x
- Spring Framework 3.2.x
- Apache Ant
TAPのインストールはこちらを参照してください。
目次
- ソースコードのダウンロード
- サンプルアプリのビルド
- Flywayの導入
- Procfileの作成
- warの更新
- pack CLIでコンテナイメージビルド
- ラップトップ上のDockerで起動
- TAPにデプロイ
- アプリの削除
ソースコードのダウンロード
レガシーなサンプルアプリはこちらからダウンロード
wget https://ftp.iij.ad.jp/pub/osdn.jp/terasoluna/66350/terasoluna-server4jweb-toursample_2.0.6.2.zip
unzip terasoluna-server4jweb-toursample_2.0.6.2.zip
cd terasoluna-server4jweb-toursample_2.0.6.2
unzip toursample-javaweb.zip
cd toursample-javaweb
サンプルアプリのビルド
MavenやGradleを使用している場合は、Cloud Native Buildpacksを使用してTAP上でソースコードのビルドから行えますが、 Antはサポートされていないので、事前にwarをビルドして、warをTAPにデプロイするようにします。
TAPで利用できる再旧バージョンであるJava 8でビルドします。antも久々にインストールします。
brew install ant
ant/build.xml
を見るとTomcatがビルドに必要なため、Tomcatをダウンロードします。
サンプルでTomcat 6が使用されていましたが、ここではTomcat 9を使用します。
Tomcat 10以降ではServlet APIのpackage名が変わっているので使用できません。
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.84/bin/apache-tomcat-9.0.84.zip
unzip apache-tomcat-9.0.84.zip -d /opt
ant/build.properties
のwebapsvr.home
をダウンロードしたディレクトリに変えます。またwarのファイル名をROOT.war
になるように変更します。
cat <<'EOF' > ant/build.properties
# Keep
source.dir=./sources
web.inf.dir=./webapps/WEB-INF
lib.dir=./webapps/WEB-INF/lib
zip.dir=./terasoluna/src
## Change according to your tomcat env
webapsvr.home=/opt/apache-tomcat-9.0.84
webapsvr.lib.dir=${webapsvr.home}/lib
deploy.dir=${webapsvr.home}/webapps
## Change
context.name=ROOT
EOF
ログの出力先を標準出力にするためにsources/log4j.properties
を次のように変更します。
cat <<EOF > sources/log4j.properties
# Keep
log4j.rootCategory=INFO, consoleLog, logfile
log4j.category.jp.terasoluna=INFO
log4j.category.org.springframework=INFO
log4j.category.org.apache.struts=INFO
log4j.appender.consoleLog=org.apache.log4j.ConsoleAppender
log4j.appender.consoleLog.Target = System.out
log4j.appender.consoleLog.layout = org.apache.log4j.PatternLayout
log4j.appender.consoleLog.layout.ConversionPattern=[%d{yyyy/MM/dd HH:mm:ss}][%p][%C{1}] %m%n
# Remove
# log4j.appender.logfile=...
EOF
これでantでビルドします。Java 8を使用してください。
ant -f ant/build.xml
ビルドできました。
Buildfile: /Users/toshiaki/blog/legacy/terasoluna-server4jweb-toursample_2.0.6.2/toursample-javaweb/ant/build.xml
clean:
[delete] Deleting: /opt/apache-tomcat-9.0.84/webapps/ROOT.war
compile:
[javac] /Users/toshiaki/blog/legacy/terasoluna-server4jweb-toursample_2.0.6.2/toursample-javaweb/ant/build.xml:69: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 97 source files to /Users/toshiaki/blog/legacy/terasoluna-server4jweb-toursample_2.0.6.2/toursample-javaweb/webapps/WEB-INF/classes
[copy] Copying 10 files to /Users/toshiaki/blog/legacy/terasoluna-server4jweb-toursample_2.0.6.2/toursample-javaweb/webapps/WEB-INF/classes
native2ascii:
[native2ascii] Converting 16 files from /Users/toshiaki/blog/legacy/terasoluna-server4jweb-toursample_2.0.6.2/toursample-javaweb/sources to /Users/toshiaki/blog/legacy/terasoluna-server4jweb-toursample_2.0.6.2/toursample-javaweb/webapps/WEB-INF/classes
build:
deploy:
[jar] Building jar: /Users/toshiaki/blog/legacy/terasoluna-server4jweb-toursample_2.0.6.2/toursample-javaweb/ROOT.war
[copy] Copying 1 file to /opt/apache-tomcat-9.0.84/webapps
[delete] Deleting: /Users/toshiaki/blog/legacy/terasoluna-server4jweb-toursample_2.0.6.2/toursample-javaweb/ROOT.war
BUILD SUCCESSFUL
Total time: 1 second
Flywayの導入
DBマイグレーションを手動で行いたくないのでFlywayを導入します。 と言ってもソースコードには手を入れたくないので、アプリの起動前にコマンドラインで実行するようにします。
wget https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/5.2.4/flyway-commandline-5.2.4-linux-x64.tar.gz
tar xzvf flyway-commandline-5.2.4-linux-x64.tar.gz
mv flyway-5.2.4/ flyway
SQLの文字コードがSHIFT_JISX0213なのでUTF-8に変換しちゃいます。変換後のファイル名はFlywayの命名規則に合わせます。
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/create_all_sequences.sql > flyway/sql/V1__create_all_sequences.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/create_all_tables.sql > flyway/sql/V2__create_all_tables.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/create_all_index.sql > flyway/sql/V3__create_all_index.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/insert_departure.sql > flyway/sql/V4__insert_departure.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/insert_arrival.sql > flyway/sql/V5__insert_arrival.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/insert_accommodation.sql > flyway/sql/V6__insert_accommodation.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/insert_age.sql > flyway/sql/V7__insert_age.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/insert_employee.sql > flyway/sql/V8__insert_employee.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/insert_customer.sql > flyway/sql/V9__insert_customer.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/insert_tourinfo.sql > flyway/sql/V10__insert_tourinfo.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/insert_tourcon.sql > flyway/sql/V11__insert_tourcon.sql
iconv -f SHIFT_JISX0213 -t UTF-8 sqls/postgres/insert_reserve.sql > flyway/sql/V12__insert_reserve.sql
Procfileの作成
Tomcat起動前にFlywayの実行や、META-INF/context.xml
に設定されているJNDIの設定を書き換えたいので、
Procfile
を使用して、任意のスクリプトで起動できるようにします。
cat <<EOF > Procfile
web: bash /workspace/run.sh
EOF
起動スクリプトはrun.sh
に記述します。
データベース(PostgreSQL)への接続情報は Service Binding で渡されるものとします。 Well-known Secret Entries のフォーマットが使用されていることを前提にします。
cat <<'EOD' > run.sh
#!/bin/bash
set -e
BINDING_NAME=tour-db
DATABASE_HOST=$(cat ${SERVICE_BINDING_ROOT}/${BINDING_NAME}/host)
DATABASE_PORT=$(cat ${SERVICE_BINDING_ROOT}/${BINDING_NAME}/port)
DATABASE_USERNAME=$(cat ${SERVICE_BINDING_ROOT}/${BINDING_NAME}/username)
DATABASE_PASSWORD=$(cat ${SERVICE_BINDING_ROOT}/${BINDING_NAME}/password)
DATABASE_NAME=$(cat ${SERVICE_BINDING_ROOT}/${BINDING_NAME}/database)
DATABASE_URL="jdbc:postgresql://${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}"
cat << EOF > ./META-INF/context.xml
<Context>
<Resource
name="jdbc/terasolunaTourDataSource"
type="javax.sql.DataSource"
driverClassName="org.postgresql.Driver"
password="${DATABASE_PASSWORD}"
maxIdle="4"
maxWait="5000"
username="${DATABASE_USERNAME}"
url="${DATABASE_URL}"
maxActive="20"/>
</Context>
EOF
${JAVA_HOME}/bin/java \
-cp `ls WEB-INF/lib/postgresql-*.jar`:./flyway/lib/community/* \
org.flywaydb.commandline.Main migrate \
-url=${DATABASE_URL} \
-user=${DATABASE_USERNAME} \
-password=${DATABASE_PASSWORD}
export CATALINA_OUT=/dev/stdout
export CATALINA_PID=/tmp/catalina.pid
bash ${CATALINA_HOME}/bin/catalina.sh start
JAVA_PID=$(cat $CATALINA_PID)
stop_java_app() {
kill -SIGTERM $JAVA_PID
}
trap stop_java_app SIGINT
while [ -e /proc/$JAVA_PID ]
do
sleep 1
done
EOD
chmod +x run.sh
warの更新
ビルドしたwarにflywayやProcfileなどを詰め込みます。またソースコードにPostgreSQLのJDBCドライバーが含まれていないので、ドライバーもダウンロードして詰め込みます。
mkdir -P WEB-INF/lib
wget https://repo1.maven.org/maven2/org/postgresql/postgresql/42.3.6/postgresql-42.3.6.jar -P WEB-INF/lib
cp /opt/apache-tomcat-9.0.84/webapps/ROOT.war ./
次のコマンドで ROOT.war
にファイルを追加します。
jar -uvf ROOT.war flyway/lib flyway/jars flyway/sql WEB-INF Procfile run.sh
pack CLIでコンテナイメージビルド
TAPにデプロイする前に pack
CLIでコンテナイメージをビルドしてローカルで起動確認します。
pack build toursample --builder paketobuildpacks/builder-jammy-base:latest --path ./ROOT.war -e BP_JVM_VERSION=8
ラップトップ上のDockerで起動
ビルドしたイメージをDockerで起動してみます。 その前にPostgreSQLを起動します。
docker run --rm \
-p 5432:5432 \
-e POSTGRES_DB=tour \
-e POSTGRES_USER=tour \
-e POSTGRES_PASSWORD=tour \
bitnami/postgresql:14
Service Binding 用のディレクトリ・ファイルを作成します。
mkdir -p bindings/tour-db
echo postgresql > bindings/tour-db/type
echo host.docker.internal > bindings/tour-db/host
echo 5432 > bindings/tour-db/port
echo tour > bindings/tour-db/username
echo tour > bindings/tour-db/password
echo tour > bindings/tour-db/database
アプリを起動します。
docker run --rm \
--name toursample \
-p 8080:8080 \
-v ${PWD}/bindings:/bindings \
-e SERVICE_BINDING_ROOT=/bindings \
-m 768m \
toursample
http://localhost:8080 にアクセスするとトップ画面に遷移します。
会員ID 00000001
, パスワード password
でログインできます。
アプリとPostgreSQLをCtrl+Cで終了してください。
TAPにデプロイ
いよいよTAPにデプロイします。
その前にPostgreSQLを用意します。ここではBitnami Serviceを使用します。 次のコマンドでPostgreSQLのインスタンスを作成します。
tanzu service class-claim create tour-db --class postgresql-unmanaged --parameter storageGB=1 -n demo
次のような状態になるまで待ちます。
$ tanzu services class-claims get tour-db --namespace demo
Name: tour-db
Namespace: demo
Claim Reference: services.apps.tanzu.vmware.com/v1alpha1:ClassClaim:tour-db
Class Reference:
Name: postgresql-unmanaged
Parameters:
storageGB: 1
Status:
Ready: True
Claimed Resource:
Name: e18f1e5a-6533-449c-b0ea-5cb4317f4c07
Namespace: demo
Group:
Version: v1
Kind: Secret
いよいよデプロイします。
tanzu apps workload apply toursample \
--app toursample \
--local-path ./ROOT.war \
--type web \
--build-env BP_JVM_VERSION=8 \
--annotation autoscaling.knative.dev/minScale=1 \
--service-ref tour-db=services.apps.tanzu.vmware.com/v1alpha1:ClassClaim:tour-db \
-n demo \
-y
ℹ️ testingを含むSupply Chainを使用している場合は、
--label apps.tanzu.vmware.com/has-tests=true
を追加してください。
ℹ️ Local Source Proxyを使用しない場合は、
--source-image
オプションで、ソースコードをアップロードするコンテナレジストリのレポジトリ名を指定してください。
進捗は次のコマンドで確認できます。
tanzu apps workload tail -n demo toursample --since 5m
しばらくするとデプロイが完了します。
$ tanzu apps workload get -n demo toursample
📡 Overview
name: toursample
type: web
namespace: demo
💾 Source
type: source image
image: 532912407632.dkr.ecr.ap-northeast-1.amazonaws.com/tap-lsp:demo-toursample@sha256:52e10a5ab3777384d104402dec839bc9017e53b8ae961fb0aa2a867e637a975b
📦 Supply Chain
name: source-test-scan-to-url
NAME READY HEALTHY UPDATED RESOURCE
source-provider True True 7m15s imagerepositories.source.apps.tanzu.vmware.com/toursample
source-tester True True 6m37s runnables.carto.run/toursample
image-provider True True 5m45s images.kpack.io/toursample
image-scanner True True 5m14s imagescans.scanning.apps.tanzu.vmware.com/toursample
config-provider True True 5m11s podintents.conventions.carto.run/toursample
app-config True True 5m11s configmaps/toursample
service-bindings True True 5m11s configmaps/toursample-with-claims
api-descriptors True True 5m11s configmaps/toursample-with-api-descriptors
config-writer True True 5m3s taskruns.tekton.dev/toursample-config-writer-4t7rp
🚚 Delivery
name: delivery-basic
NAME READY HEALTHY UPDATED RESOURCE
source-provider True True 4m11s imagerepositories.source.apps.tanzu.vmware.com/toursample-delivery
deployer True True 3m17s apps.kappctrl.k14s.io/toursample
💬 Messages
No messages found.
🔁 Services
CLAIM NAME KIND API VERSION
tour-db tour-db ClassClaim services.apps.tanzu.vmware.com/v1alpha1
🛶 Pods
NAME READY STATUS RESTARTS AGE
scan-toursample-5w5tv-pod 0/6 Completed 0 5m45s
toursample-00001-deployment-5d955b64b6-bdfn9 2/2 Running 0 4m9s
toursample-build-1-build-pod 0/1 Completed 0 6m37s
toursample-config-writer-4t7rp-pod 0/1 Completed 0 5m10s
toursample-jlsmz-test-pod 0/1 Completed 0 6m59s
🚢 Knative Services
NAME READY URL
toursample Ready https://toursample.demo.tap.57.180.147.144.sslip.io
To see logs: "tanzu apps workload tail toursample --namespace demo --timestamp --since 1h"
URLにアクセスすれば、画面が表示されます。
ログインもできます。
アプリの削除
tanzu apps workload delete -n demo toursample -y
tanzu service class-claim delete tour-db -n demo