Gradleの基本:bootRunやbootJarとは何か?

Spring Boot Gradleプラグインが提供する主要タスク

Spring BootでGradleを使う場合、org.springframework.bootプラグインを適用すると、開発に必要なタスクが自動的に追加されます。代表的なのは、アプリを直接起動するbootRun、実行可能JARを作成するbootJar、Dockerイメージを生成するbootBuildImageの3つです。

このプラグインはJavaプラグインを前提として動作し、標準のjarタスクを拡張する形でbootJarが機能します。具体的には、Spring Bootプラグイン適用時に標準のjarタスクはplainというクラシファイア付きに変更され、bootJarが実質的なパッケージングを担います。

タスク名 役割 主な用途
bootRun ソースコードからアプリを直接起動 開発中の動作確認
bootJar 実行可能なfat JARを作成 本番用成果物の生成
bootBuildImage Dockerfile不要でOCIイメージを作成 コンテナデプロイ向け

GradleでSpring Bootアプリを扱う基本は、これら3つのタスクを目的に応じて使い分けることです(出典:Spring Boot公式ドキュメント「Reacting to the Java Plugin」)。

実行可能JAR(fat JAR)の仕組み

bootJarが生成するのは、実行可能なuber JAR(fat JAR)です。通常のJARと異なり、アプリのクラスだけでなく依存ライブラリもすべて1つのファイルに含まれます。

内部構造は、アプリのクラスがBOOT-INF/classes、依存JARがBOOT-INF/libに配置され、Spring Bootの起動ローダーがこれらを読み込んでアプリを起動します。メインクラスはMain-ClassStart-Classがマニフェストに自動設定されるため、手動でメインクラスを指定する必要はありません

成果物はbuild/libs/プロジェクト名-バージョン.jarとして出力され、./gradlew buildを実行するとassembleタスク経由でbootJarも自動実行されます(出典:Spring Boot公式ドキュメント「Reacting to the Java Plugin」)。

Gradle WrapperとJavaバージョンの関係

Spring Bootプロジェクトを扱う前に、Gradle Wrapperの利用が公式推奨であることを理解しておきましょう。Wrapperを使うと、プロジェクトごとにGradleのバージョンを固定でき、チームやCI環境で同じビルド環境を再現できます。

Gradleを実行するにはJDK 17以上が必要です。ただし、Gradle自体を実行するJDKと、Spring Bootアプリをコンパイル・実行するJavaバージョンは別物です。Java Toolchainsを使えば、Gradleの実行環境とプロジェクトのJava環境を分離できます。

Spring Boot 4.xはGradle 8.14以降とGradle 9.xをサポートしているため、Gradle 9.6.1との組み合わせに問題はありません(出典:Gradle公式ドキュメント「Compatibility Matrix」)。

Spring Boot Gradleプラグインは、bootRun・bootJar・bootBuildImageの3タスクを中心に、開発から本番デプロイまでを1つのビルドツールで完結させます。

bootRunの正しい使い方と終わらない問題の対処法

bootRunの基本的な使い方

bootRunは、ビルドせずにソースコードとruntime classpathからアプリを直接起動する開発用タスクです。コマンドは./gradlew bootRunで、コードの変更を反映しながら素早く動作確認できます。

起動時に引数を渡したい場合は、--argsオプションを使います。例えばポートを変更するなら./gradlew bootRun --args='--server.port=8081'と指定します。また、applicationプラグインを適用している場合、mainClassNameapplicationDefaultJvmArgsの設定をbootRunが自動的に引き継ぎます。

  • コマンド:./gradlew bootRun
  • 引数指定:./gradlew bootRun --args='--server.port=8081'
  • テスト用起動:./gradlew bootTestRun(テストソースセットで起動)

開発中はこのタスクを使うことで、JARファイルを作る手間を省いて即座にアプリの挙動を確認できます(出典:Spring Boot公式ドキュメント「Reacting to the Java Plugin」)。

bootRunが終わらない理由と対処法

bootRunアプリを起動したまま待機し続けるタスクです。そのため「コマンドが終わらない」と感じるのは、実は正常な動作です。Spring BootアプリはWebサーバーを内蔵しており、停止命令があるまでプロセスが動き続けます。

終了するには、ターミナルでCtrl + Cを押してプロセスを中断します。もし「タスクが終了しない」のではなく「ビルドが失敗する」「アプリが起動しない」という場合は、ポート競合や設定ミスが原因の可能性があります。その場合は--args='--server.port=8081'で別ポートを指定するか、ログを確認して原因を特定しましょう。

また、bootRunは開発専用です。本番環境ではbootJarで生成した実行可能JARをjava -jarで起動するのが正しい使い方です(出典:Spring Boot公式ドキュメント「Reacting to the Java Plugin」)。

bootRunと通常のjava -jar実行の違い

bootRunと実行可能JARを使った起動は、起動方法と利用シーンが異なります。bootRunはソースコードから直接起動するため、ビルド工程をスキップして素早く起動できる反面、本番環境での利用は想定されていません。

実行可能JARはbootJarで生成された成果物をjava -jar application.jarで起動します。こちらはビルド済みの成果物を使うため、どの環境でも同じ動作を再現できます。

比較項目 bootRun java -jar
ビルド工程 不要(ソースから直接起動) 必要(bootJarで事前に生成)
主な利用シーン 開発中の動作確認 本番・検証環境での起動
起動速度 ビルド分だけ速い JAR生成後に起動
環境再現性 開発環境に依存 どの環境でも同じ

bootRunは「終わらないタスク」ではなく、アプリを起動し続ける開発用タスクです。停止するにはCtrl + Cを使い、本番ではbootJarで生成したJARをjava -jarで起動します。

bootJarとbootWarの違い:実行可能JARの作成方法

bootJarとbootWarの使い分け

bootJar実行可能なJARファイルを、bootWar実行可能なWARファイルを作成するタスクです。どちらを使うかは、アプリのデプロイ方法によって決まります。

JARはSpring Bootの組み込みWebサーバー(Tomcatなど)を含むため、java -jarだけで起動できる自己完結型の成果物です。一方、WARは外部のServletコンテナ(TomcatやWildFlyなど)にデプロイして動かす形式で、既存のアプリケーションサーバー環境を利用する場合に選択します。

Spring BootではJAR形式がデフォルトであり、クラウド環境やコンテナデプロイではJARが主流です。

  • bootJar:組み込みサーバーを含む自己完結型JARを作成
  • bootWar:外部ServletコンテナにデプロイするWARを作成

(出典:Spring Boot公式ドキュメント「Reacting to the Java Plugin」)

bootJarで実行可能JARを作成する手順

実行可能JARの作成は、Spring Boot Gradleプラグインを適用するだけでほぼ完了します。特別な設定を追加しなくても、メインクラスの自動検出とマニフェスト設定が行われます。

  1. build.gradleにSpring Bootプラグインを適用する
  2. ./gradlew bootJarを実行する
  3. build/libs/プロジェクト名-バージョン.jarが生成される
  4. java -jar 生成されたJARファイルで起動確認する

JARの内部は、アプリのクラスがBOOT-INF/classes、依存ライブラリがBOOT-INF/libに配置されます。また、./gradlew buildを実行すると、assembleタスク経由でbootJarも自動実行されるため、通常のビルドフローに組み込まれています(出典:Spring Boot公式ドキュメント「Reacting to the Java Plugin」)。

レイヤードJARの仕組みと利点

Spring BootはJARをレイヤ分割する仕組みをサポートしており、Dockerイメージの効率的な構築に役立ちます。デフォルトでは、依存ライブラリ・Spring Bootローダー・スナップショット依存・アプリコードの4レイヤに分かれます。

レイヤ名 内容 変更頻度
dependencies リリース済みの依存ライブラリ
spring-boot-loader Spring Boot起動コード
snapshot-dependencies スナップショット依存
application アプリのクラス・リソース

レイヤ分割を使うと、変更頻度の低い依存ライブラリをDockerイメージのキャッシュとして再利用できるため、コード変更時のイメージ再構築が高速になります。レイヤの抽出にはjava -Djarmode=tools -jar app.jar extract --layersコマンドを使用します(出典:Spring Boot公式ドキュメント「Efficient Container Images」)。

bootJarは組み込みサーバーを含む自己完結型JARを作成し、コンテナデプロイの標準形式です。レイヤードJARを活用するとDockerイメージ構築の効率が大幅に向上します。

Dockerイメージ作成はbootBuildImageとDockerfileの2つの方法

bootBuildImageでDockerfile不要のイメージ作成

bootBuildImageは、Dockerfileを書かずに1コマンドでOCIイメージを作成できるSpring Bootの公式機能です。Cloud Native Buildpacks(CNB)を使い、Paketo buildpacksが自動的にJREを組み込んで本番向けイメージを生成します。

実行コマンドは./gradlew bootBuildImageで、デフォルトのイメージ名はdocker.io/library/プロジェクト名:バージョンです。イメージ名を指定する場合は--imageName=example.com/library/my-app:v1のようにオプションを付けます。ビルドにはローカルでDockerデーモンが起動している必要があります

  • コマンド:./gradlew bootBuildImage
  • イメージ名指定:./gradlew bootBuildImage --imageName=example.com/my-app:v1
  • 前提条件:ローカルでDockerデーモンが起動していること

生成されたイメージはレイヤードJARとSBOM(ソフトウェア部品表)を含む本番向け構成ですが、デフォルトのUbuntuベースのためイメージサイズは約400MBと大きめです(出典:Spring Boot公式ドキュメント「Cloud Native Buildpacks」)。

Dockerfileによる手動構築とマルチステージビルド

Dockerfileを使う方法は、より細かい制御ができる反面、効率的なイメージを作るための知識が必要です。単純にfat JARをコピーするだけでは、アプリコードと全依存が同一レイヤになり、コード変更のたびに全レイヤを再構築することになります。

公式推奨はレイヤードJARを抽出してからDockerイメージにコピーするマルチステージビルドです。まずビルダーステージでjava -Djarmode=tools -jar application.jar extract --layers --destination extractedを実行してJARをレイヤ分割し、実行ステージで各レイヤを個別にコピーします。これにより、変更頻度の低い依存ライブラリはDockerのキャッシュを活用できます。

  1. ビルダーステージでJARをレイヤ抽出する
  2. 実行ステージで各レイヤを個別にコピーする
  3. 軽量なJREイメージをベースに使用する
  4. ENTRYPOINT ["java", "-jar", "application.jar"]で起動する

(出典:Spring Boot公式ドキュメント「Dockerfiles」)

2つの方法の比較と選び方

どちらの方法を選ぶかは、プロジェクトの要件とチームのスキルセットによって判断します。bootBuildImageは手軽さが最大の利点で、Dockerの知識が少なくても本番向けイメージを生成できます。

比較項目 bootBuildImage Dockerfile
Dockerfileの必要性 不要 必要
設定の柔軟性 低い(builder設定に依存) 高い(自由にカスタマイズ可能)
イメージサイズ 約400MB(Ubuntuベース) 軽量JRE選択で約200〜400MBに調整可能
OSパッケージの追加 難しい 容易
学習コスト 低い 高い

手軽に始めるならbootBuildImage、イメージサイズや構成を細かく最適化したいならDockerfileという使い分けが現実的です(出典:Spring Boot公式ドキュメント「Container Images」)。

bootBuildImageはDockerfile不要で本番向けイメージを1コマンド生成、DockerfileはレイヤードJARと軽量JREを組み合わせることでイメージサイズと再構築効率を最適化できます。

GradleでSpring Bootをパッケージ化する際の注意点

バージョン互換性の確認ポイント

Spring BootをGradleでパッケージ化する際、JDK・Gradle・Spring Bootプラグインの3つのバージョン互換性を最初に確認する必要があります。Gradleを実行するにはJDK 17以上が必要で、Spring Boot 4.xはGradle 8.14以降とGradle 9.xをサポートしています。

特に注意したいのは、「Gradleを実行するJDK」と「アプリをコンパイル・実行するJavaバージョン」は別物という点です。Java Toolchainsを使えば、Gradleの実行環境とは異なるJavaバージョンでプロジェクトをビルドできます。新規プロジェクトでは、最新安定版の組み合わせ(Gradle 9.6.1 + Spring Bootプラグイン4.1.0)を選ぶのが確実です。

  • Gradle実行環境:JDK 17以上が必要
  • Spring Boot 4.x:Gradle 8.14+ / 9.xをサポート
  • Java Toolchainsで実行環境とビルド対象のJavaを分離可能

(出典:Gradle公式ドキュメント「Compatibility Matrix」、Spring Boot 4.0 Release Notes)

標準jarタスクの変更に注意

Spring Boot Gradleプラグインを適用すると、標準のjarタスクの動作が変わります。具体的には、jarタスクが生成する成果物にplainというクラシファイアが付き、bootJarがメインのパッケージングタスクになります。

そのため、既存のGradleプロジェクトにSpring Bootプラグインを追加した場合、build/libs/プロジェクト名-バージョン.jar(bootJar)とプロジェクト名-バージョン-plain.jar(標準jar)の2つが生成されることがあります。通常はbootJarの成果物をデプロイに使用しますが、標準jarと混同しないよう注意が必要です。

また、./gradlew buildを実行すると、assembleタスク経由でbootJarも自動実行されるため、明示的にbootJarを指定しなくても実行可能JARが生成されます(出典:Spring Boot公式ドキュメント「Reacting to the Java Plugin」)。

コンテナ用JVM設定のベストプラクティス

DockerコンテナでSpring Bootアプリを実行する場合、JVMのメモリ設定をコンテナ環境に合わせることが重要です。Java 10以降はUseContainerSupportがデフォルトで有効なため、コンテナのメモリ制限をJVMが自動認識します。

推奨される設定は、固定のヒープサイズではなく-XX:MaxRAMPercentage=75.0のようにコンテナのメモリ制限に対する割合で指定する方法です。これにより、コンテナのメモリ制限が変わってもJVMが適切に追従します。

  • 推奨:-XX:MaxRAMPercentage=75.0(コンテナメモリの75%を上限に使用)
  • Java 10以降:UseContainerSupportがデフォルト有効
  • セキュリティ:非rootユーザーでアプリを実行する

また、コンテナイメージでは非rootユーザーでアプリを実行することがセキュリティ上のベストプラクティスです(出典:Spring Boot公式ドキュメント「Efficient Container Images」)。

パッケージ化の前にJDK・Gradle・Spring Bootプラグインの互換性を確認し、標準jarタスクの変更を理解した上で、コンテナ環境では割合ベースのメモリ設定と非root実行を適用します。