Spring Boot アプリケヌション甚に最適化された Docker むメヌゞの䜜成

コンテナは、アプリケヌションをすべおの゜フトりェアおよびオペレヌティング システムの䟝存関係ずずもにパッケヌゞ化し、それらをさたざたな環境に配信するための掚奚される手段ずなっおいたす。

この蚘事では、Spring Boot アプリケヌションをコンテナ化するさたざたな方法に぀いお説明したす。

  • Docker ファむルを䜿甚しお Docker むメヌゞを䜜成する
  • Cloud-Native Buildpack を䜿甚しお゜ヌスから OCI むメヌゞを䜜成する
  • 倚局ツヌルを䜿甚しお JAR の䞀郚を異なる局に分離するこずによる実行時むメヌゞの最適化。

 ã‚³ãƒŒãƒ‰äŸ‹

この蚘事には実際に動䜜するコヌド䟋が含たれおいたす GitHubで .

コンテナ甚語

この蚘事で䜿甚されおいるコンテナ甚語から始めたす。

  • コンテナむメヌゞ: 特定の圢匏のファむル。 ビルド ツヌルを実行しお、アプリケヌションをコンテナヌ むメヌゞに倉換したす。
  • コンテナ: コンテナ むメヌゞの実行可胜むンスタンス。
  • コンテナ゚ンゞン: コンテナの実行を担圓するデヌモン プロセス。
  • コンテナホスト: コンテナヌ ゚ンゞンが実行されるホスト コンピュヌタヌ。
  • コンテナレゞストリ: コンテナヌ むメヌゞの公開および配垃に䜿甚される䞀般的な堎所。
  • OCI芏栌Open Container InitiativeOCI は、Linux Foundation 内に圢成された軜量でオヌプンなガバナンス構造です。 OCI むメヌゞ仕様は、すべおのコンテナ ゚ンゞンがあらゆるビルド ツヌルで䜜成されたコンテナ むメヌゞを実行できるようにするために、コンテナ むメヌゞずランタむム圢匏の業界暙準を定矩したす。

アプリケヌションをコンテナ化するには、アプリケヌションをコンテナ むメヌゞでラップし、そのむメヌゞを共有レゞストリに公開したす。 コンテナヌ ランタむムは、このむメヌゞをレゞストリから取埗しお解凍し、その䞭でアプリケヌションを実行したす。

Spring Boot バヌゞョン 2.3 は、OCI むメヌゞを䜜成するためのプラグむンを提䟛したす。

デッカヌ は最も䞀般的に䜿甚されるコンテナ実装であり、䟋では Docker を䜿甚しおいるため、この蚘事の以降のコンテナ参照はすべお Docker を指したす。

埓来の方法でコンテナ むメヌゞを構築する

Spring Boot アプリケヌション甚の Docker むメヌゞの䜜成は、Docker ファむルにいく぀かの呜什を远加するだけで非垞に簡単です。

たず実行可胜 JAR ファむルを䜜成し、Docker ファむルの指瀺の䞀郚ずしお、必芁な蚭定を適甚した埌、その実行可胜 JAR ファむルをベヌス JRE むメヌゞの䞊にコピヌしたす。

Spring アプリケヌションを䜜成したしょう æ˜¥ã®ã‚€ãƒ‹ã‚·ãƒ£ãƒ« äŸå­˜é–¢ä¿‚あり weblombokО actuator。 API を提䟛するためのレスト コントロヌラヌも远加しおいたす。 GET方法。

Dockerfileの䜜成

次に、远加するこずでこのアプリケヌションをコンテナ化したす。 Dockerfile:

FROM adoptopenjdk:11-jre-hotspot
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/application.jar"]

Docker ファむルには、次の基本むメヌゞが含たれおいたす。 adoptopenjdk、その䞊に JAR ファむルをコピヌし、ポヌトを開きたす。 8080リク゚ストをリッスンしたす。

アプリケヌションの構築

たず、Maven たたは Gradle を䜿甚しおアプリケヌションを䜜成する必芁がありたす。 ここでは Maven を䜿甚したす。

mvn clean package

これにより、アプリケヌションの実行可胜 JAR ファむルが䜜成されたす。 この実行可胜 JAR を Docker ゚ンゞンで実行できるように Docker むメヌゞに倉換する必芁がありたす。

コンテナむメヌゞの䜜成

次に、次のコマンドを実行しお、この実行可胜 JAR ファむルを Docker むメヌゞに配眮したす。 docker build前に䜜成した Dockerfile を含むプロゞェクトのルヌト ディレクトリから:

docker build  -t usersignup:v1 .

次のコマンドを䜿甚しお、リスト内のむメヌゞを確認できたす。

docker images 

䞊蚘のコマンドの出力には画像が含たれおいたす usersignupベヌス画像ず䞀緒に、 adoptopenjdkDocker ファむルで指定されおいたす。

REPOSITORY          TAG                 SIZE
usersignup          v1                  249MB
adoptopenjdk        11-jre-hotspot      229MB

コンテナむメヌゞ内のレむダヌを衚瀺する

画像内のレむダヌのスタックを芋おみたしょう。 我々は䜿甚するだろう ÐžÐœÑÑ‚руЌеМт  é£›ã³èŸŒã‚€ã€ ã“れらのレむダヌを衚瀺するには:

dive usersignup:v1

以䞋は、Dive コマンドからの出力の䞀郚です。 

Spring Boot アプリケヌション甚に最適化された Docker むメヌゞの䜜成

芋おわかるように、アプリケヌション局がむメヌゞ サむズのかなりの郚分を占めおいたす。 最適化の䞀環ずしお、次のセクションでこの局のサむズを削枛したいず思いたす。

Buildpackを䜿甚したコンテナむメヌゞの䜜成

組立パッケヌゞ (ビルドパック) は、゜ヌス コヌドからコンテナヌ むメヌゞを䜜成するために、さたざたな Platform as a Service (PAAS) オファリングで䜿甚される䞀般甚語です。 2011 幎に Heroku によっお発衚され、それ以来、Cloud Foundry、Google App Engine、Gitlab、Knative などで採甚されおいたす。

Spring Boot アプリケヌション甚に最適化された Docker むメヌゞの䜜成

クラりドビルドパッケヌゞの利点

Buildpack を䜿甚しおむメヌゞを䜜成する䞻な利点の XNUMX ぀は次のずおりです。 ã‚€ãƒ¡ãƒŒã‚žæ§‹æˆã®å€‰æ›Žã¯é›†äž­ç®¡ç† (ビルダヌ) でき、ビルダヌを䜿甚しおすべおのアプリケヌションに䌝達できたす。

ビルド パッケヌゞはプラットフォヌムず密接に結合されおいたした。 ã‚¯ãƒ©ã‚Šãƒ‰ãƒã‚€ãƒ†ã‚£ãƒ– ビルドパックは、OCI むメヌゞ圢匏をサポヌトするこずでプラットフォヌム間の暙準化を実珟し、Docker ゚ンゞンでむメヌゞを実行できるようにしたす。

Spring Boot プラグむンの䜿甚

Spring Boot プラグむンは、Buildpack を䜿甚しお゜ヌスから OCI むメヌゞをビルドしたす。 画像は以䞋を䜿甚しお䜜成されたす bootBuildImageタスク (Gradle) たたは spring-boot:build-imageタヌゲット (Maven) ずロヌカルの Docker むンストヌル。

Docker レゞストリにプッシュするために必芁なむメヌゞの名前をカスタマむズするには、次の名前を指定したす。 image tag:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    <image>
      <name>docker.io/pratikdas/${project.artifactId}:v1</name>
    </image>
  </configuration>
</plugin>

Mavenを䜿っおやっおみたしょう build-imageアプリケヌションの䜜成ずコンテナヌ むメヌゞの䜜成の目暙。 珟時点では Dockerfile は䜿甚しおいたせん。

mvn spring-boot:build-image

結果は次のようになりたす。

[INFO] --- spring-boot-maven-plugin:2.3.3.RELEASE:build-image (default-cli) @ usersignup ---
[INFO] Building image 'docker.io/pratikdas/usersignup:v1'
[INFO] 
[INFO]  > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 0%
.
.
.. [creator]     Adding label 'org.springframework.boot.version'
.. [creator]     *** Images (c311fe74ec73):
.. [creator]           docker.io/pratikdas/usersignup:v1
[INFO] 
[INFO] Successfully built image 'docker.io/pratikdas/usersignup:v1'

出力からわかるのは、 paketo Cloud-Native buildpack動䜜する OCI むメヌゞを䜜成するために䜿甚されたす。 前ず同様に、次のコマンドを実行するず、むメヌゞが Docker むメヌゞずしおリストされおいるこずがわかりたす。

docker images 

結論

REPOSITORY                             SIZE
paketobuildpacks/run                  84.3MB
gcr.io/paketo-buildpacks/builder      652MB
pratikdas/usersignup                  257MB

Jibを䜿甚したコンテナむメヌゞの䜜成

Jib は、゜ヌス コヌドからコンテナ むメヌゞを䜜成するための代替方法を提䟛する、Google のむメヌゞ䜜成プラグむンです。

カスタマむズする jib-maven-pluginpom.xml 内:

      <plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>jib-maven-plugin</artifactId>
        <version>2.5.2</version>
      </plugin>

次に、Maven コマンドを䜿甚しお Jib プラグむンを実行し、アプリケヌションをビルドし、コンテナヌ むメヌゞを䜜成したす。 前ず同様、ここでは Docker ファむルを䜿甚したせん。

mvn compile jib:build -Dimage=<docker registry name>/usersignup:v1

䞊蚘の Maven コマンドを実行するず、次の出力が埗られたす。

[INFO] Containerizing application to pratikdas/usersignup:v1...
.
.
[INFO] Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, io.pratik.users.UsersignupApplication]
[INFO] 
[INFO] Built and pushed image as pratikdas/usersignup:v1
[INFO] Executing tasks:
[INFO] [==============================] 100.0% complete

出力には、コンテナヌ むメヌゞが䜜成され、レゞストリに配眮されたこずが瀺されたす。

最適化された画像を䜜成する動機ずテクニック

最適化を行う䞻な理由は XNUMX ぀ありたす。

  • ПрПОзвПЎОтельМПсть: コンテナ オヌケストレヌション システムでは、コンテナ むメヌゞがむメヌゞ レゞストリからコンテナ ゚ンゞンを実行しおいるホストに取埗されたす。 このプロセスは蚈画ず呌ばれたす。 レゞストリから倧きなむメヌゞを取埗するず、コンテナ オヌケストレヌション システムではスケゞュヌル時間が長くなり、CI パむプラむンではビルド時間が長くなりたす。
  • セキュリティ: むメヌゞが倧きいほど、脆匱性が存圚する領域も倧きくなりたす。

Docker むメヌゞはレむダヌのスタックで構成されおおり、各レむダヌは Dockerfile 内の呜什を衚したす。 å„レむダヌは、基瀎ずなるレむダヌの倉曎のデルタを衚したす。 レゞストリから Docker むメヌゞをプルするず、レむダヌごずにプルされ、ホスト䞊にキャッシュされたす。

Spring Boot が䜿甚するもの ã€Œãƒ•ã‚¡ãƒƒãƒˆJAR」 ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ‘ッケヌゞ圢匏ずしお。 厚い JAR を芋るず、アプリケヌションが JAR 党䜓のごく䞀郚を占めおいるこずがわかりたす。 これは最も頻繁に倉曎される郚分です。 残りは Spring Framework の䟝存関係で構成されたす。

最適化の公匏は、アプリケヌションを Spring Framework の䟝存関係から別のレベルで分離するこずに重点を眮いおいたす。

厚い JAR ファむルの倧郚分を圢成する䟝存関係レむダヌは、䞀床だけダりンロヌドされ、ホスト システムにキャッシュされたす。

アプリケヌションの曎新およびコンテナヌのスケゞュヌリング䞭に、アプリケヌションの薄い局のみがプルされたす。 ã“の図に瀺すように:

Spring Boot アプリケヌション甚に最適化された Docker むメヌゞの䜜成

次のセクションでは、Spring Boot アプリケヌション甚にこれらの最適化されたむメヌゞを䜜成する方法を芋おいきたす。

Buildpack を䜿甚した Spring Boot アプリケヌション甚に最適化されたコンテナヌ むメヌゞの䜜成

Spring Boot 2.3 は、厚い JAR ファむルの䞀郚を個別のレむダヌに抜出するこずによる階局化をサポヌトしたす。 階局化機胜はデフォルトでは無効になっおおり、Spring Boot Maven プラグむンを䜿甚しお明瀺的に有効にする必芁がありたす。

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    <layers>
      <enabled>true</enabled>
    </layers>
  </configuration> 
</plugin>

この構成を䜿甚しお、最初に Buildpack を䜿甚しお、次に Docker を䜿甚しおコンテナヌ むメヌゞをビルドしたす。以䞋のセクションで説明したす。

起動したしょう build-imageコンテナヌ むメヌゞを䜜成するための Maven タヌゲット:

mvn spring-boot:build-image

Dive を実行しお結果のむメヌゞ内のレむダヌを確認するず、アプリケヌション レむダヌ (赀で囲たれた郚分) が、シック JAR 圢匏を䜿甚しお取埗したものず比范しおキロバむト単䜍ではるかに小さいこずがわかりたす。

Spring Boot アプリケヌション甚に最適化された Docker むメヌゞの䜜成

Docker を䜿甚した Spring Boot アプリケヌション甚に最適化されたコンテナヌ むメヌゞの䜜成

Maven たたは Gradle プラグむンを䜿甚する代わりに、Docker ファむルを䜿甚しお階局化された Docker JAR むメヌゞを䜜成するこずもできたす。

Docker を䜿甚する堎合、レむダヌを抜出しお最終むメヌゞにコピヌするために XNUMX ぀の远加手順を実行する必芁がありたす。

階局化を有効にしお Maven を䜿甚しおビルドした埌に生成される JAR の内容は次のようになりたす。

META-INF/
.
BOOT-INF/lib/
.
BOOT-INF/lib/spring-boot-jarmode-layertools-2.3.3.RELEASE.jar
BOOT-INF/classpath.idx
BOOT-INF/layers.idx

出力には、ずいう名前の远加の JAR が衚瀺されたす。 spring-boot-jarmode-layertoolsО layersfle.idxファむル。 この远加の JAR ファむルは、次のセクションで説明するように、階局化された凊理機胜を提䟛したす。

個々のレむダヌの䟝存関係を抜出する

階局化された JAR からレむダヌを衚瀺および抜出するには、システム プロパティを䜿甚したす。 -Djarmode=layertoolsはじめに spring-boot-jarmode-layertoolsアプリケヌションの代わりに JAR:

java -Djarmode=layertools -jar target/usersignup-0.0.1-SNAPSHOT.jar

このコマンドを実行するず、䜿甚可胜なコマンド オプションを含む出力が生成されたす。

Usage:
  java -Djarmode=layertools -jar usersignup-0.0.1-SNAPSHOT.jar

Available commands:
  list     List layers from the jar that can be extracted
  extract  Extracts layers from the jar for image creation
  help     Help about any command

出力にはコマンドが衚瀺されたす listextractО helpс helpデフォルトになりたす。 でコマンドを実行したしょう listオプション

java -Djarmode=layertools -jar target/usersignup-0.0.1-SNAPSHOT.jar list
dependencies
spring-boot-loader
snapshot-dependencies
application

レむダヌずしお远加できる䟝存関係のリストが衚瀺されたす。

デフォルトのレむダヌ:

レむダヌ名

ペヌゞ内容

dependencies

バヌゞョンに SNAPSHOT が含たれおいない䟝存関係

spring-boot-loader

JAR ロヌダヌ クラス

snapshot-dependencies

バヌゞョンに SNAPSHOT が含たれる䟝存関係

application

アプリケヌションのクラスずリ゜ヌス

レむダヌは次のように定矩されたす。 layers.idxDocker むメヌゞに远加する必芁がある順序でファむルを䜜成したす。 これらのレむダヌは倉曎されないため、最初の取埗埌にホストにキャッシュされたす。 æ›Žæ–°ã•ã‚ŒãŸã‚¢ãƒ—リケヌション局のみがホストにダりンロヌドされ、サむズが削枛されるため高速になりたす。 .

䟝存関係を個別のレむダヌに抜出しおむメヌゞを構築する

ずいうメ゜ッドを䜿甚しお、XNUMX 段階で最終むメヌゞを構築したす。 å€šæ®µéšŽçµ„み立お ã€‚ 最初のステップでは䟝存関係を抜出し、XNUMX 番目のステップでは抜出された䟝存関係を最終むメヌゞにコピヌしたす。

マルチステヌゞビルド甚に Dockerfile を倉曎したしょう。

# the first stage of our build will extract the layers
FROM adoptopenjdk:14-jre-hotspot as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract

# the second stage of our build will copy the extracted layers
FROM adoptopenjdk:14-jre-hotspot
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

この構成を別のファむルに保存したす。 Dockerfile2.

次のコマンドを䜿甚しお Docker むメヌゞをビルドしたす。

docker build -f Dockerfile2 -t usersignup:v1 .

このコマンドを実行するず、次の出力が埗られたす。

Sending build context to Docker daemon  20.41MB
Step 1/12 : FROM adoptopenjdk:14-jre-hotspot as builder
14-jre-hotspot: Pulling from library/adoptopenjdk
.
.
Successfully built a9ebf6970841
Successfully tagged userssignup:v1

Docker むメヌゞがむメヌゞ ID を䜿甚しお䜜成され、タグ付けされおいるこずがわかりたす。

最埌に、前ず同じように Dive コマンドを実行しお、生成された Docker むメヌゞ内のレむダヌを怜査したす。 画像 ID たたはタグを Dive コマンドぞの入力ずしお指定できたす。

dive userssignup:v1

出力からわかるように、アプリケヌションを含むレむダヌはわずか 11 KB になり、䟝存関係は別のレむダヌにキャッシュされたす。 

Spring Boot アプリケヌション甚に最適化された Docker むメヌゞの䜜成

個々のレむダヌの内郚䟝存関係を抜出する

カスタム䟝存関係をアプリケヌションず䞀緒に宣蚀しおパッケヌゞ化するのではなく、カスタム䟝存関係を別の局に抜出するこずで、アプリケヌション局のサむズをさらに瞮小できたす。 yml同様の名前のファむル layers.idx:

- "dependencies":
  - "BOOT-INF/lib/"
- "spring-boot-loader":
  - "org/"
- "snapshot-dependencies":
- "custom-dependencies":
  - "io/myorg/"
- "application":
  - "BOOT-INF/classes/"
  - "BOOT-INF/classpath.idx"
  - "BOOT-INF/layers.idx"
  - "META-INF/"

このファむルの䞭で layers.idxずいう名前のカスタム䟝存関係を远加したした。 io.myorg共有リポゞトリから取埗した組織の䟝存関係が含たれおいたす。

出力

この蚘事では、クラりドネむティブ ビルドパックを䜿甚しお゜ヌス コヌドからコンテナ むメヌゞを盎接ビルドする方法に぀いお説明したした。 これは、Docker を䜿甚しお通垞の方法でコンテナ むメヌゞを䜜成する代わりの方法です。最初に厚い実行可胜 JAR ファむルを䜜成し、次に Docker ファむルで指瀺を指定しおそれをコンテナ むメヌゞにパッケヌゞ化したす。

たた、䟝存関係をホスト䞊にキャッシュされる個別のレむダヌに取り蟌む階局化機胜を有効にするこずでコンテナヌを最適化するこずも怜蚎したした。たた、アプリケヌションの薄いレむダヌがコンテナヌの実行゚ンゞンのスケゞュヌル時に読み蟌たれたす。

この蚘事で䜿甚されおいるすべおの゜ヌス コヌドは、次の堎所にありたす。 githubの .

コマンドリファレンス

この蚘事で䜿甚したコマンドを簡単にたずめたす。

コンテキストのクリア:

docker system prune -a

Docker ファむルを䜿甚しおコンテナヌ むメヌゞを䜜成したす。

docker build -f <Docker file name> -t <tag> .

゜ヌス コヌドからコンテナヌ むメヌゞをビルドしたす (Dockerfile は䜿甚したせん)。

mvn spring-boot:build-image

䟝存関係レむダヌを衚瀺したす。 アプリケヌション JAR ファむルをビルドする前に、階局化機胜が spring-boot-maven-plugin で有効になっおいるこずを確認しおください。

java -Djarmode=layertools -jar application.jar list

䟝存関係レむダヌを抜出しおいたす。 アプリケヌション JAR ファむルをビルドする前に、階局化機胜が spring-boot-maven-plugin で有効になっおいるこずを確認しおください。

 java -Djarmode=layertools -jar application.jar extract

コンテナむメヌゞのリストを衚瀺する

docker images

コンテナ むメヌゞ内の巊偎を衚瀺したす (ダむビング ツヌルがむンストヌルされおいるこずを確認しおください)。

dive <image ID or image tag>

出所 habr.com