0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GlassFish → Payara を経験して見えた、WAR モデルの限界

0
Last updated at Posted at 2025-11-21

はじめに

業務で長く GlassFish を使い、Payara への移行とコンテナ化も経験しました。しかし、運用や開発の負担が期待したほど軽くならず、「アプリケーションサーバに WAR を載せる」構成そのものを見直す必要を感じました。

ただし、この経験から「Payara の Docker イメージは重い」「Spring Boot の JAR は Docker と相性がよい」と単純化するのは正確ではありません。Docker で配布・再利用される単位は WAR や JAR というファイル形式ではなく、Dockerfile の各命令が作るレイヤーです。Payara でもベースイメージを再利用でき、Spring Boot でも fat JAR を一枚のレイヤーにコピーすれば、変更のたびに JAR 全体が新しいレイヤーになります。

この記事で整理したい論点は、WAR と JAR の優劣ではありません。外部アプリケーションサーバへアーカイブをデプロイする方式と、アプリケーションが実行ランタイムを内包して自己完結する方式では、設定、起動、デプロイ、障害対応の境界がどのように変わるのか、という点です。

先に訂正したいこと:コンテナイメージの差分は WAR か JAR かでは決まらない

Docker イメージは複数のレイヤーで構成されます。変更されたレイヤーと、その後に続くレイヤーは再ビルド対象になりますが、変わらないベースレイヤーは再利用できます。Docker の公式ドキュメント でも、各 Dockerfile 命令がレイヤーとなり、あるレイヤーの変更が後続レイヤーのキャッシュを無効にすることが説明されています。

Payara は公式の Docker イメージを提供しており、WAR を配置するカスタムイメージも作れます。Payara の公式ドキュメント にある方式は、次のようなものです。

FROM payara/server-full
COPY app.war $DEPLOY_DIR/app.war

この構成では、Payara 本体は payara/server-full のベースレイヤーです。アプリケーションを更新しても変わるのは主に COPY で追加した WAR のレイヤーであり、レジストリ側に同じベースレイヤーがあれば、それを改めて転送する必要はありません。したがって、「外部アプリケーションサーバを使うと、更新のたびに巨大なイメージ全体を push する」という理解は誤りです。

一方、Spring Boot の fat JAR をそのままコピーする Dockerfile もあります。

FROM eclipse-temurin:21-jre
COPY app.jar /app/app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

この場合、アプリケーションコードを少し変更しただけでも app.jar 全体が新しいレイヤーになります。fat JAR にはアプリケーションコードだけでなく依存ライブラリや Spring Boot のローダーも含まれうるため、レイヤー設計をしなければ差分を小さくできるとは限りません。

Spring Boot はこの課題に対応するため、依存ライブラリ、ローダー、スナップショット依存、アプリケーションコードを分離する layered JAR をサポートしています。Spring Boot の公式ドキュメント は、変わりにくい依存関係と変わりやすいアプリケーションコードを別レイヤーに置くことで、キャッシュを活用できると説明しています。さらに、このレイヤー化は JAR だけでなく WAR でも利用できます。

比較すべきなのは、ファイル形式ではなくデプロイモデル

WAR と JAR はパッケージ形式です。しかし、実際に開発・運用の負荷へ影響するのは、実行時に誰がランタイムと設定を所有し、どの単位で起動・更新・監視するかです。ここでは、外部アプリケーションサーバ型と自己完結型という二つのデプロイモデルとして整理します。

観点 外部アプリケーションサーバ型 自己完結型アプリケーション
実行時の構成 サーバランタイムを起動し、その上へアプリケーションアーカイブをデプロイします。 アプリケーションのプロセスが HTTP サーバなどの実行機能を内包します。
主な設定の境界 サーバのドメイン設定、起動時コマンド、環境変数、アプリ側設定を分けて管理します。 アプリケーションの設定と起動引数を中心に管理しやすい構成です。
デプロイ単位 サーバとアーカイブの組み合わせです。複数アプリケーションを同じサーバへ載せる設計も選べます。 原則としてアプリケーションごとにイメージとプロセスを持ちます。
更新時の論点 アーカイブの更新に加え、デプロイ処理、サーバ設定との整合、再デプロイの挙動を確認します。 アプリケーションイメージを入れ替え、プロセスを切り替える流れを設計しやすい構成です。
イメージ配布量 ベースイメージと WAR を別レイヤーにすれば、変更したレイヤーを中心に配布できます。 fat JAR を一枚でコピーすると JAR 全体が更新対象です。layered JAR で分割できます。

この違いは「Payara は Kubernetes で使えない」「Spring Boot なら自動的にクラウドネイティブになる」という意味ではありません。Payara の公式イメージは、ドメインをフォアグラウンドで起動して JVM をコンテナの主プロセスとして扱い、アプリケーションをデプロイ用ディレクトリから配置できます。Payara の公式ドキュメント が示すように、Payara をコンテナとして運用すること自体は十分に可能です。

Payara を使うときに残る運用上の境界

Payara をコンテナ化しても、アプリケーションサーバという運用モデルは残ります。ここでいう負担はイメージの転送量ではなく、サーバ設定、起動シーケンス、デプロイ処理、アプリケーション設定の関係を継続して理解・管理することです。

たとえば Payara では、アプリケーションを配置するディレクトリのほか、環境変数、事前・事後の管理コマンド、初期化スクリプトでドメインを設定できます。これは柔軟性でもありますが、設定がアプリケーションコード、コンテナ定義、ドメイン設定、起動スクリプトへ分散しやすいことも意味します。設定をどこに置くか、何をイメージに含めるか、どの変更で再デプロイが必要かをチームで明確にしなければなりません。

複数のアプリケーションを一つのアプリケーションサーバへ載せ、共通のリソースや管理機能を使う場合には、この分離は合理的です。一方で、アプリケーションをサービス単位で独立してリリースし、設定もスケールも個別に持たせたい場合は、共有するサーバの存在が調整コストになることがあります。

開発体験で見るべきポイント

「WAR は遅く、JAR は速い」と決めつける前に、実際の待ち時間を分解して測定する必要があります。開発時の反映時間には、ビルド、アーカイブ作成、コンテナビルド、コンテナ起動、サーバの初期化、アプリケーションのデプロイ、フレームワークの初期化が含まれます。どこが支配的かは、アプリケーションの規模、利用する Jakarta EE 機能、データベース接続、開発支援機能、Dockerfile のレイヤー設計によって変わります。

確認したい項目 外部アプリケーションサーバ型で確認すること 自己完結型で確認すること
コード変更の反映 WAR 作成から再デプロイ完了までの時間と、失敗時に残る状態を確認します。 アプリケーション再起動または開発支援機能による反映時間を確認します。
設定変更の反映 アプリ設定、ドメイン設定、起動コマンドのどれを変えるかを区別します。 設定ファイル、環境変数、起動引数のどれを変えるかを区別します。
起動時間 サーバ起動とアプリケーション配備を分けて計測します。 JVM 起動、組み込みサーバ起動、アプリ初期化を分けて計測します。
障害時の切り分け サーバログ、デプロイ結果、アプリログ、管理設定を関連付けます。 プロセスログ、アプリ設定、依存サービスとの接続を関連付けます。

私が GlassFish から Payara へ移行した際に「軽くならない」と感じたのは、主にこの運用上の境界でした。コンテナ化によって配布と起動の形は整えられても、アプリケーションサーバの設定・起動・デプロイを管理する必要は残ります。自己完結型アプリケーションと比べると、その関係を把握する対象が増えやすい点が、開発時の負担につながりました。

どちらを選ぶべきか

外部アプリケーションサーバ型が不適切なのではありません。Jakarta EE の機能を統合的に利用したい場合、複数アプリケーションでリソースや運用機能を共有したい場合、既存の基盤・監視・セキュリティ運用がアプリケーションサーバを前提としている場合には、有力な選択肢です。

一方、サービスごとに独立してビルド、設定、リリース、スケール、ロールバックを行いたい場合は、自己完結型の構成が理解しやすくなります。その場合も、Spring Boot の JAR をそのまま一枚の Docker レイヤーに置くのではなく、依存関係とアプリケーションコードの変更頻度を意識してレイヤー化を検討します。

設計判断では、次の順番で考えると混同を避けられます。

  1. まず、アプリケーションをどの単位で起動・更新・スケールさせたいかを決めます。
  2. 次に、サーバ設定とアプリケーション設定をどこに置き、誰が変更責任を持つかを決めます。
  3. 最後に、そのデプロイモデルに合うパッケージ形式と Dockerfile のレイヤー構成を選びます。

まとめ

GlassFish から Payara へ移行して分かったのは、Payara が Docker や Kubernetes と相性が悪いということではありません。Payara でも公式イメージをベースレイヤーとして再利用でき、WAR 更新時の差分を抑えたコンテナイメージを作れます。反対に、Spring Boot の fat JAR をそのままコピーすれば、依存ライブラリを含む JAR 全体が変更レイヤーになります。

課題になりやすいのは、WAR という拡張子そのものではなく、外部アプリケーションサーバへアプリケーションをデプロイする運用モデルです。この方式では、サーバ設定、起動、デプロイ、アプリケーション設定の境界を管理し続けます。その柔軟性が必要な場面もありますが、サービス単位の独立性を重視する環境では、自己完結型アプリケーションのほうが構成を単純にしやすい場合があります。

この記事の結論は、「WAR を使うべきではない」ではありません。イメージの軽さを WAR と JAR の対立として判断せず、どのデプロイモデルがチームの開発・運用の単位に合うかを基準に選ぶべき、ということです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?