Docker で Spring Boot

このガイドでは、Spring Boot アプリケーションを実行するための Docker (英語) イメージを構築する手順を説明します。まずは基本的な Dockerfile から始めて、いくつかの調整を行います。次に、docker の代わりにビルドプラグイン (Maven および Gradle 用) を使用するいくつかのオプションを示します。これは「入門」ガイドであるため、範囲はいくつかの基本的なニーズに限定されています。本番環境で使用するコンテナーイメージを構築する場合、考慮すべき点が多く、短いガイドですべてを網羅することは不可能です。

Docker のトピックガイドもあり、これはここで紹介した選択肢よりも幅広い選択肢を、より詳細にカバーしています。

構築するもの

Docker (英語) は、ユーザーがコンテナーイメージを公開したり、他のユーザーが公開したコンテナーイメージを使用できるようにする、「ソーシャル」な側面を持つ Linux コンテナー管理ツールキットです。Docker イメージは、コンテナー化されたプロセスを実行するためのレシピです。このガイドでは、シンプルな Spring boot アプリケーション用に 1 つを構築します。

必要なもの

Docker (英語) も必要です。お使いのマシンに Docker を設定する方法については、https://docs.docker.com/installation/#installation (英語) を参照してください。先に進む前に、シェルから docker コマンドを実行できることを確認してください。

Spring Initializr から開始

IDE を使用する場合はプロジェクト作成ウィザードを使用します。IDE を使用せずにコマンドラインなどで開発する場合は、この事前に初期化されたプロジェクトからプロジェクトを ZIP ファイルとしてダウンロードできます。このプロジェクトは、このチュートリアルの例に合うように構成されています。

プロジェクトを手動で初期化するには:

  1. IDE のメニューまたはブラウザーから Spring Initializr を開きます。アプリケーションに必要なすべての依存関係を取り込み、ほとんどのセットアップを行います。

  2. Gradle または Maven のいずれかと、使用する言語を選択してください。

  3. 依存関係をクリックして、Spring Web を選択します。

  4. 生成をクリックします。

  5. 結果の ZIP ファイルをダウンロードします。これは、選択して構成された Web アプリケーションのアーカイブです。

Eclipse や IntelliJ のような IDE は新規プロジェクト作成ウィザードから Spring Initializr の機能が使用できるため、手動での ZIP ファイルのダウンロードやインポートは不要です。
プロジェクトを GitHub からフォークして、IDE または他のエディターで開くこともできます。

Spring Boot アプリケーションを設定する

これで、シンプルなアプリケーションを作成できます(Java の場合は src/main/java/hello/Application.java、Kotlin の場合は src/main/kotlin/hello/Application.kt を使用)。

Java
package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class Application {

	@RequestMapping("/")
	public String home() {
		return "Hello Docker World";
	}

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}
Kotlin
package hello

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@SpringBootApplication
@RestController
class Application {

    @RequestMapping("/")
    fun home() = "Hello Docker World"

}

fun main(args: Array<String>) {
    runApplication<Application>(*args)
}

このクラスは @SpringBootApplication および @RestController としてフラグ付けされており、Spring MVC が Web リクエストを処理するために使用できる状態になっています。@RequestMapping は / を home() メソッドにマッピングし、Hello World レスポンスを送信します。main() メソッドは、Spring Boot の SpringApplication.run() メソッドを使用してアプリケーションを起動します。Kotlin では、代わりに runApplication が使用されます。

これで、Docker コンテナーなしで (つまり、ホスト OS で) アプリケーションを実行できます。

Gradle
./gradlew build && java -jar build/libs/spring-boot-docker-complete-0.0.1-SNAPSHOT.jar
Maven
./mvnw package && java -jar target/spring-boot-docker-complete-0.0.1-SNAPSHOT.jar

次に、localhost:8080 に移動して、"Hello Docker World" メッセージを確認します。

コンテナー化

Docker には、イメージの「レイヤー」を指定するために使用するシンプルな "Dockerfile" (英語) ファイル形式があります。Spring Boot プロジェクトで次の Dockerfile を作成します。

例 1: Dockerfile
FROM eclipse-temurin:17
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

以下のコマンドを実行してください。

Gradle
docker build --build-arg 'JAR_FILE=build/libs/*-SNAPSHOT.jar' -t springio/gs-spring-boot-docker .
Maven
docker build -t springio/gs-spring-boot-docker .

このコマンドはイメージを構築し、springio/gs-spring-boot-docker としてタグ付けします。

この Dockerfile は非常にシンプルですが、Spring Boot アプリを余計な機能なしで実行するために必要なのは、Java と JAR ファイルだけです。COPY コマンドを使用して、プロジェクトの JAR ファイルをコンテナーに app.jar としてコピーし、ENTRYPOINT で実行します。Dockerfile の ENTRYPOINT は配列形式を使用しているため、Java プロセスがシェルラップされることはありません。

Tomcat の起動時間 [Apache] (英語) を減らすために、エントロピーのソースとして /dev/urandom を指すシステムプロパティを追加していました。JDK 8 以降 (英語) ではこれは必要ありません。

ユーザー権限でアプリケーションを実行すると、いくつかのリスクを軽減できます (例: StackExchange のスレッド (英語) を参照)。Dockerfile の重要な改善点は、アプリケーションを非ルートユーザーとして実行することです。

例 2: Dockerfile
FROM eclipse-temurin:17
RUN addgroup --system spring && adduser --system --ingroup spring spring
USER spring:spring
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

以下のコマンドを使用してアプリケーションをビルドして実行すると、アプリケーションの起動ログにユーザー名が表示されます。

Gradle
./gradlew build
docker build --build-arg 'JAR_FILE=build/libs/*-SNAPSHOT.jar' -t springio/gs-spring-boot-docker .
docker run -p 8080:8080 springio/gs-spring-boot-docker
Maven
./mvnw package
docker build -t springio/gs-spring-boot-docker .
docker run -p 8080:8080 springio/gs-spring-boot-docker

最初の INFO ログエントリの started by に注意してください。

 :: Spring Boot ::                (v4.1.1)

2026-09-30T12:47:53.827Z  INFO 1 --- [           main] hello.Application                        : Starting Application v0.0.1-SNAPSHOT using Java 17.0.19 with PID 1 (/app.jar started by spring in /)
...

また、Spring Boot ファット JAR ファイルでは依存関係とアプリケーションリソースが明確に分離されており、この事実を利用してパフォーマンスを向上させることができます。鍵となるのは、コンテナーファイルシステムにレイヤーを作成することです。レイヤーはビルド時と実行時 (ほとんどの実行時) の両方でキャッシュされるため、最も頻繁に変更されるリソース (通常はアプリケーション自体のクラスリソースと静的リソース) は、変更が遅いリソースの後にレイヤー化する必要があります。そのため、Dockerfile のわずかに異なる実装を使用します。

Java
FROM eclipse-temurin:17
RUN addgroup --system spring && adduser --system --ingroup spring spring
USER spring:spring
ARG DEPENDENCY=target/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]
Kotlin
FROM eclipse-temurin:17
RUN addgroup --system spring && adduser --system --ingroup spring spring
USER spring:spring
ARG DEPENDENCY=build/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.ApplicationKt"]

この Dockerfile には、ファット JAR を展開したディレクトリを指す DEPENDENCY パラメーターがあります。DEPENDENCY パラメーターを使用するには、次のコマンドを実行します。

Gradle
mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*-SNAPSHOT.jar)
Maven
mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)

正しく理解していれば、依存関係 JAR ファイルを含む BOOT-INF/lib ディレクトリと、アプリケーションクラスを含む BOOT-INF/classes ディレクトリがすでに存在しているはずです。最上位の main 関数は ApplicationKt クラスにコンパイルされるため、アプリケーション自身のメインクラス(Java では hello.Application、Kotlin では hello.ApplicationKt)を使用していることに注意してください。(これは、ファット JAR ランチャーによって提供される間接参照を使用するよりも高速です。)

JAR ファイルを展開すると、実行時にクラスパスの順序が変わる [GitHub] (英語) 可能性があります。適切に動作し、適切に記述されたアプリケーションでは、この点は課題になりませんが、依存関係が適切に管理されていない場合は、動作が変わることがあります。

イメージをビルドするには、次のコマンドを実行します(Gradle ビルドでは、Docker コマンドラインで明示的なビルド引数を指定する必要があります)。

Gradle
docker build --build-arg DEPENDENCY=build/dependency -t springio/gs-spring-boot-docker .
Maven
docker build -t springio/gs-spring-boot-docker .
Gradle のみを使用する場合は、Dockerfile を変更して、DEPENDENCY のデフォルト値を解凍済みアーカイブの場所に一致させることができます。Gradle のみで構築された Kotlin サンプルプロジェクトは、まさにこの方法を採用しているため、--build-arg DEPENDENCY=build/dependency 引数は不要です。

Docker コマンドラインでビルドする代わりに、ビルドプラグインを使用することもできます。Spring Boot は、独自のビルドプラグインを使用して、Maven または Gradle からコンテナーをビルドすることをサポートしています。Google には、Maven および Gradle プラグインを備えた Jib [GitHub] (英語) というオープンソースツールもあります。おそらく、このアプローチの最も興味深い点は、Dockerfile が必要ないことです。docker build から取得するのと同じ標準コンテナー形式を使用してイメージをビルドできます。また、docker がインストールされていない環境でも機能します (ビルドサーバーでは珍しいことではありません)。

デフォルトでは、デフォルトの buildpacks によって生成されたイメージは、アプリケーションをルートとして実行しません。デフォルト設定を変更する方法については、Gradle または Maven の構成ガイドを確認してください。

Spring Boot ビルドプラグインを使用して Docker イメージをビルドする

タグ付き docker イメージは、ビルド構成を変更することなく、1 つのコマンドでビルドできます(Dockerfile がまだ存在する場合は無視されることに注意してください)。

Gradle
./gradlew bootBuildImage --imageName=springio/gs-spring-boot-docker
Maven
./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=springio/gs-spring-boot-docker

Docker レジストリにプッシュするには、プッシュ権限が必要ですが、デフォルトではこの権限がありません。Docker を実行する前に、イメージのプレフィックスを自分の Dockerhub ID と docker login に変更して、認証されていることを確認してください。

プッシュ後

例の docker push は失敗します (Dockerhub の "springio" 組織に属している場合を除く)。ただし、自分の docker ID と一致するように構成を変更すると、成功するはずです。すると、新しいタグ付きイメージがデプロイされます。

ローカルでビルドされた docker イメージを実行するために、docker に登録したり、何かを公開したりする必要はありません。Docker (コマンドラインまたは Spring Boot から) を使用してビルドした場合は、ローカルでタグ付けされたイメージがまだあるため、次のように実行できます。

$ docker run -p 8080:8080 -t springio/gs-spring-boot-docker
Calculating JVM memory based on 7373112K available memory
For more information on this calculation, see https://paketo.io/docs/reference/java-reference/#memory-calculator
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx6785158K -XX:MaxMetaspaceSize=75953K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 7373112K, Thread Count: 250, Loaded Class Count: 10996, Headroom: 0%)
...
2026-09-30T12:52:44.656Z  INFO 1 --- [           main] o.s.boot.tomcat.TomcatWebServer          : Tomcat started on port 8080 (http) with context path '/'
2026-09-30T12:52:44.660Z  INFO 1 --- [           main] hello.Application                        : Started Application in 0.678 seconds (process running for 0.843)
buildpack は実行時にメモリ計算機を使用して、コンテナーに適合するように JVM のサイズを決定します。

その後、アプリケーションは http://localhost:8080 で利用できるようになります (そこにアクセスすると、"Hello Docker World" と表示されます)。

実行中は、次の例のようなコンテナーのリストが表示されます。

$ docker ps
CONTAINER ID        IMAGE                                   COMMAND                  CREATED             STATUS              PORTS                    NAMES
81c723d22865        springio/gs-spring-boot-docker:latest   "/cnb/process/web"       34 seconds ago      Up 33 seconds       0.0.0.0:8080->8080/tcp   goofy_brown

再度シャットダウンするには、前のリストに表示されたコンテナー ID または名前(お使いの環境によって異なります)を使用して docker stop を実行します。

docker stop goofy_brown

必要に応じて、使用が終わったらコンテナーを削除することもできます (コンテナーはファイルシステムの /var/lib/docker のどこかに保存されます)。

docker rm goofy_brown

Spring プロファイルの使用

新しく作成した Docker イメージを Spring プロファイルで実行するのは、環境変数を Docker 実行コマンド (prod プロファイルの場合) に渡すだけです。

docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker

dev プロファイルでも同じことができます。

docker run -e "SPRING_PROFILES_ACTIVE=dev" -p 8080:8080 -t springio/gs-spring-boot-docker

Docker コンテナーでのアプリケーションのデバッグ

アプリケーションをデバッグするには、JPDA 輸送 [Oracle] を使用できます。コンテナーを リモートサーバーのように扱います。この機能を有効にするには、コンテナーの実行中に JAVA_OPTS 変数で Java エージェント設定を渡し、エージェントのポートを localhost にマップします。Mac 用 Docker (英語) では、ブラックマジックを使用し [GitHub] (英語) ないと IP でコンテナーにアクセスできないため、制限があります。

docker run -e "JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n" -p 8080:8080 -p 5005:5005 -t springio/gs-spring-boot-docker

要約

おめでとうございます ! Spring Boot アプリケーション用の Docker コンテナーを作成しました ! デフォルトでは、Spring Boot アプリケーションはコンテナー内のポート 8080 で実行され、コマンドラインで -p を使用して、それをホスト上の同じポートにマッピングしました。

関連事項

次のガイドも役立つかもしれません:

新しいガイドを作成したり、既存のガイドに貢献したいですか? 投稿ガイドラインを参照してください [GitHub] (英語) 。

すべてのガイドは、コード用の ASLv2 ライセンス、およびドキュメント用の帰属表示、NoDerivatives クリエイティブコモンズライセンス (英語) でリリースされています。

コードを入手する