概要
記事一覧はこちらです。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その17 )( app コンテナを実行する Alpine Linux で ja_JP.utf8 のロケールを使えるようにする ) の続きです。
参照したサイト・書籍
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
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
5.Packaging OCI Images
https://docs.spring.io/spring-boot/docs/2.3.7.RELEASE/gradle-plugin/reference/html/#build-image
Cloud Native Buildpacks
https://buildpacks.io/
paketo - Java Buildpack
https://paketo.io/docs/buildpacks/language-family-buildpacks/java/
Buildpacksのビルダーをスクラッチから作ってみる
https://future-architect.github.io/articles/20201002/
Creating Optimized Docker Images for a Spring Boot Application
https://reflectoring.io/spring-boot-docker/
目次
- bootBuildImage タスクで Docker image を生成する
- 生成した Docker image で app コンテナを起動する
- messages_ja_JP.properties → messages_ja.properties にリネームして日本語のメッセージが表示されるようにする
- 最後に
手順
bootBuildImage タスクで Docker image を生成する
Gradle Tool Window を見ると bootBuildImage タスクがありますので実行します。

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

右側には以下のログが出力されていました。
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 を見つけました。

生成した Docker image で app コンテナを起動する
docker-compose.app.yml を以下のように変更します。
services:
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
..........
- 以前の 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 コンテナを起動します。

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

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 コマンドはインストールされていないようです。

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)
のメッセージが出力されて設定できませんでした。

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

docker/app/Dockerfile で build した Docker image で Web アプリを起動しても、docker/app/Dockerfile を glibc をインストールしないバージョンに戻してから Docker image を作り直して Web アプリを起動しても、Windows の IntelliJ IDEA から Web アプリを起動しても、日本語のメッセージが表示されました。そうか、これで良かったのか。。。
最後に
bootBuildImage タスクを実行するだけで Docker image が簡単に作れます。Spring Boot、ますます便利になった印象です。
履歴
2020/12/29
初版発行。