かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その18 )( Build OCI images with Cloud Native Buildpacks を試してみる )

概要

記事一覧はこちらです。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その17 )( app コンテナを実行する Alpine Linux で ja_JP.utf8 のロケールを使えるようにする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Build OCI images with Cloud Native Buildpacks に記載されていますが、2.3 から Cloud Native Buildpacks を使って Docker image を生成する機能が追加されました。この機能を利用して Docker image を生成し、Web アプリを動かしてみます。

参照したサイト・書籍

  1. Build OCI images with Cloud Native Buildpacks
    https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#build-oci-images-with-cloud-native-buildpacks

  2. 31.Building Container Images
    https://docs.spring.io/spring-boot/docs/2.3.7.RELEASE/reference/html/spring-boot-features.html#boot-features-container-images

  3. 5.Packaging OCI Images
    https://docs.spring.io/spring-boot/docs/2.3.7.RELEASE/gradle-plugin/reference/html/#build-image

  4. Cloud Native Buildpacks
    https://buildpacks.io/

  5. paketo - Java Buildpack
    https://paketo.io/docs/buildpacks/language-family-buildpacks/java/

  6. Buildpacksのビルダーをスクラッチから作ってみる
    https://future-architect.github.io/articles/20201002/

  7. Creating Optimized Docker Images for a Spring Boot Application
    https://reflectoring.io/spring-boot-docker/

目次

  1. bootBuildImage タスクで Docker image を生成する
  2. 生成した Docker image で app コンテナを起動する
  3. messages_ja_JP.properties → messages_ja.properties にリネームして日本語のメッセージが表示されるようにする
  4. 最後に

手順

bootBuildImage タスクで Docker image を生成する

Gradle Tool Window を見ると bootBuildImage タスクがありますので実行します。

f:id:ksby:20201228231313p:plain

Successfully built image 'docker.io/library/ksbysample-webapp-lending:2.3.7-RELEASE'BUILD SUCCESSFUL のメッセージが出力されて Docker image の生成に成功しました。

f:id:ksby:20201228231602p:plain

右側には以下のログが出力されていました。

23:13:27: Executing task 'bootBuildImage'...

> Task :bootBuildInfo
> Task :copyDomaResources UP-TO-DATE
> Task :compileJava UP-TO-DATE
> Task :compileGroovy NO-SOURCE
> Task :generateGitProperties
> Task :processResources
> Task :classes
> Task :bootJar

> Task :bootBuildImage
Building image 'docker.io/library/ksbysample-webapp-lending:2.3.7-RELEASE'

 > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' ..................................................
 > Pulled builder image 'gcr.io/paketo-buildpacks/builder@sha256:88d93729c291dfdf320fa21a8f8ae2c1d7366f9e602f4eab6ed88cec653f9d7d'
 > Pulling run image 'docker.io/paketobuildpacks/run:base-cnb' ..................................................
 > Pulled run image 'paketobuildpacks/run@sha256:f393fa2927a2619a10fc09bb109f822d20df909c10fed4ce3c36fad313ea18e3'
 > Executing lifecycle version v0.10.1
 > Using build cache volume 'pack-cache-50ed1ff0b3a5.build'

 > Running creator
    [creator]     ===> DETECTING
    [creator]     5 of 18 buildpacks participating
    [creator]     paketo-buildpacks/ca-certificates   1.0.1
    [creator]     paketo-buildpacks/bellsoft-liberica 6.0.0
    [creator]     paketo-buildpacks/executable-jar    3.1.3
    [creator]     paketo-buildpacks/dist-zip          2.2.2
    [creator]     paketo-buildpacks/spring-boot       3.5.0
    [creator]     ===> ANALYZING
    [creator]     Restoring metadata for "paketo-buildpacks/ca-certificates:helper" from app image
    [creator]     Restoring metadata for "paketo-buildpacks/bellsoft-liberica:helper" from app image
    [creator]     Restoring metadata for "paketo-buildpacks/bellsoft-liberica:java-security-properties" from app image
    [creator]     Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jre" from app image
    [creator]     Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jvmkill" from app image
    [creator]     Restoring metadata for "paketo-buildpacks/executable-jar:class-path" from app image
    [creator]     Restoring metadata for "paketo-buildpacks/spring-boot:helper" from app image
    [creator]     Restoring metadata for "paketo-buildpacks/spring-boot:spring-cloud-bindings" from app image
    [creator]     Restoring metadata for "paketo-buildpacks/spring-boot:web-application-type" from app image
    [creator]     ===> RESTORING
    [creator]     ===> BUILDING
    [creator]     
    [creator]     Paketo CA Certificates Buildpack 1.0.1
    [creator]       https://github.com/paketo-buildpacks/ca-certificates
    [creator]       Launch Helper: Reusing cached layer
    [creator]     
    [creator]     Paketo BellSoft Liberica Buildpack 6.0.0
    [creator]       https://github.com/paketo-buildpacks/bellsoft-liberica
    [creator]       Build Configuration:
    [creator]         $BP_JVM_VERSION              11.*            the Java version
    [creator]       Launch Configuration:
    [creator]         $BPL_JVM_HEAD_ROOM           0               the headroom in memory calculation
    [creator]         $BPL_JVM_LOADED_CLASS_COUNT  35% of classes  the number of loaded classes in memory calculation
    [creator]         $BPL_JVM_THREAD_COUNT        250             the number of threads in memory calculation
    [creator]         $JAVA_TOOL_OPTIONS                           the JVM launch flags
    [creator]       BellSoft Liberica JRE 11.0.9: Reusing cached layer
    [creator]       Launch Helper: Reusing cached layer
    [creator]       JVMKill Agent 1.16.0: Reusing cached layer
    [creator]       Java Security Properties: Reusing cached layer
    [creator]     
    [creator]     Paketo Executable JAR Buildpack 3.1.3
    [creator]       https://github.com/paketo-buildpacks/executable-jar
    [creator]       Process types:
    [creator]         executable-jar: java org.springframework.boot.loader.JarLauncher
    [creator]         task:           java org.springframework.boot.loader.JarLauncher
    [creator]         web:            java org.springframework.boot.loader.JarLauncher
    [creator]     
    [creator]     Paketo Spring Boot Buildpack 3.5.0
    [creator]       https://github.com/paketo-buildpacks/spring-boot
    [creator]       Launch Helper: Reusing cached layer
    [creator]       Web Application Type: Contributing to layer
    [creator]         Servlet web application detected
    [creator]         Writing env.launch/BPL_JVM_THREAD_COUNT.default
    [creator]       Spring Cloud Bindings 1.7.0: Reusing cached layer
    [creator]       Image labels:
    [creator]         org.springframework.boot.spring-configuration-metadata.json
    [creator]         org.springframework.boot.version
    [creator]     ===> EXPORTING
    [creator]     Reusing layer 'paketo-buildpacks/ca-certificates:helper'
    [creator]     Reusing layer 'paketo-buildpacks/bellsoft-liberica:helper'
    [creator]     Reusing layer 'paketo-buildpacks/bellsoft-liberica:java-security-properties'
    [creator]     Reusing layer 'paketo-buildpacks/bellsoft-liberica:jre'
    [creator]     Reusing layer 'paketo-buildpacks/bellsoft-liberica:jvmkill'
    [creator]     Reusing layer 'paketo-buildpacks/executable-jar:class-path'
    [creator]     Reusing layer 'paketo-buildpacks/spring-boot:helper'
    [creator]     Reusing layer 'paketo-buildpacks/spring-boot:spring-cloud-bindings'
    [creator]     Reusing layer 'paketo-buildpacks/spring-boot:web-application-type'
    [creator]     Adding 1/1 app layer(s)
    [creator]     Reusing layer 'launcher'
    [creator]     Reusing layer 'config'
    [creator]     Adding label 'io.buildpacks.lifecycle.metadata'
    [creator]     Adding label 'io.buildpacks.build.metadata'
    [creator]     Adding label 'io.buildpacks.project.metadata'
    [creator]     Adding label 'org.springframework.boot.spring-configuration-metadata.json'
    [creator]     Adding label 'org.springframework.boot.version'
    [creator]     *** Images (7904578079ee):
    [creator]           docker.io/library/ksbysample-webapp-lending:2.3.7-RELEASE

Successfully built image 'docker.io/library/ksbysample-webapp-lending:2.3.7-RELEASE'


Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.5.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 19s
7 actionable tasks: 5 executed, 2 up-to-date
23:13:46: Task execution finished 'bootBuildImage'.

IntelliJ IDEA で Docker image を見ると ksbysample-webapp-lending:2.3.7-RELEASE が生成されていることが確認できました。Size が 328.2MB と結構大きいです。あと Created が 41 years ago でした。。。なぜ?(bootBuildImage タスクを実行すると 41年後に飛ばされることを知ったのはこの少し後でした。今私は未来から bootBuildImage タスクを実行してはいけないことを警告するためにこのブログを書いていますwww)

理由を調べたら Spring Boot 2.3.0 buildpack builds image with creation date 40 years ago を見つけました。

f:id:ksby:20201228232001p:plain

生成した Docker image で app コンテナを起動する

docker-compose.app.yml を以下のように変更します。

services:
#  # docker/app/Dockerfile で生成した docker image を利用する場合の設定
#  app:
#    build:
#      context: .
#      dockerfile: docker/app/Dockerfile
#    image: ksbysample-webapp-lending
#    volumes:
#      - ./build/libs/ksbysample-webapp-lending-2.3.7-RELEASE.jar:/app.jar
#      - ./docker/app/docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh
#    environment:
#      - SPRING_DATASOURCE_HIKARI_JDBC_URL=jdbc:postgresql://postgresql/ksbylending
#      - SPRING_MAIL_HOST=mail-server
#      - SPRING_RABBITMQ_HOST=haproxy
#    deploy:
#      mode: replicated
#      replicas: 3
#    # entrypoint: /bin/sh
#    # stdin_open: true
#    # tty: true

  # bootBuildImage で生成した docker image を利用する場合の設定
  # docker exec -it ksbysample-webapp-lending_app_1 /bin/bash
  app:
    image: ksbysample-webapp-lending:2.3.7-RELEASE
    environment:
      - JAVA_TOOL_OPTIONS=-Dspring.profiles.active=product -Dlogging.appender=CONSOLE
      - SPRING_DATASOURCE_HIKARI_JDBC_URL=jdbc:postgresql://postgresql/ksbylending
      - SPRING_MAIL_HOST=mail-server
      - SPRING_RABBITMQ_HOST=haproxy
    deploy:
      mode: replicated
      replicas: 3
    # entrypoint: /bin/bash
    # stdin_open: true
    # tty: true

..........
  • 以前の app コンテナの設定は全てコメントアウトし、新しい app コンテナの設定を追加します。
  • Docker image が ksbysample-webapp-lending:2.3.7-RELEASE で生成されているので、image にこれを記述します。
  • environment には以前の app コンテナに指定していたものを全てコピーした後、docker/app/docker-entrypoint.sh で指定していた JVM の起動時オプションのうち -Dspring.profiles.active=product -Dlogging.appender=CONSOLE の2つを指定したいので、Runtime JVM Configuration を参考に JAVA_TOOL_OPTIONS=-Dspring.profiles.active=product -Dlogging.appender=CONSOLE を追加します。

docker-compose -f docker-compose.app.yml --compatibility up -d コマンドで app コンテナを起動します。

f:id:ksby:20201229152643p:plain

Spring Boot のロゴの前に出力されているログは以下の内容でした。

Setting Active Processor Count to 2
Calculating JVM memory based on 2722764K available memory
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx2066762K -XX:MaxMetaspaceSize=144001K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 2722764K, Thread Count: 250, Loaded Class Count: 23010, Headroom: 0%)
Adding 138 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Dspring.profiles.active=product -Dlogging.appender=CONSOLE -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=2 -XX:MaxDirectMemorySize=10M -Xmx2066762K -XX:MaxMetaspaceSize=144001K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true

http://localhost:8080/ にアクセスするとログイン画面が表示されてログインして機能も一通り動いたのですが、ログイン画面で何も入力せずに「ログイン」ボタンをクリックしたら日本語のメッセージが表示されませんでした。

f:id:ksby:20201229153231p:plain

messages_ja_JP.properties → messages_ja.properties にリネームして日本語のメッセージが表示されるようにする

docker exec -it ksbysample-webapp-lending_app_1 /bin/bash コマンドで起動した app コンテナの1つに接続して locate -a コマンドを実行してみましたが、locate: command not found のメッセージが出力されました。locale コマンドはインストールされていないようです。

f:id:ksby:20201229154319p:plain

locale を設定する方法を Web で調べてみましたが、それらしい情報がヒットしません。

docker-compose.app.yml で環境変数 LANG、LC_ALL に ja_JP.UTF-8 を設定してみても、

  app:
    image: ksbysample-webapp-lending:2.3.7-RELEASE
    environment:
      - JAVA_TOOL_OPTIONS=-Dspring.profiles.active=product -Dlogging.appender=CONSOLE
      - SPRING_DATASOURCE_HIKARI_JDBC_URL=jdbc:postgresql://postgresql/ksbylending
      - SPRING_MAIL_HOST=mail-server
      - SPRING_RABBITMQ_HOST=haproxy
      - LANG=ja_JP.UTF-8
      - LC_ALL=ja_JP.UTF-8
    deploy:
      mode: replicated
      replicas: 3

bash: warning: setlocale: LC_ALL: cannot change locale (ja_JP.utf8) のメッセージが出力されて設定できませんでした。

f:id:ksby:20201229162630p:plain

どう対応してよいのか良く分からなくなったのですが、メッセージを見直してみると ... for locale 'ja'. と出力されており、もしかして ja_JP ではなく ja?と思ってファイル名を messages_ja_JP.properties → messages_ja.properties に変更してみたところ日本語のメッセージが表示されるようになりました。

f:id:ksby:20201229163821p:plain

docker/app/Dockerfile で build した Docker image で Web アプリを起動しても、docker/app/Dockerfile を glibc をインストールしないバージョンに戻してから Docker image を作り直して Web アプリを起動しても、WindowsIntelliJ IDEA から Web アプリを起動しても、日本語のメッセージが表示されました。そうか、これで良かったのか。。。

最後に

bootBuildImage タスクを実行するだけで Docker image が簡単に作れます。Spring Boot、ますます便利になった印象です。

履歴

2020/12/29
初版発行。