かんがるーさんの日記

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

IntelliJ IDEA を 2020.2.4 → 2020.3.1 へ、Git for Windows を 2.29.2.2 → 2.30.0 へバージョンアップ

IntelliJ IDEA を 2020.2.4 → 2020.3.1 へバージョンアップする

IntelliJ IDEA の 2020.3.1 がリリースされているのでバージョンアップします。

※ksbysample-webapp-lending プロジェクトを開いた状態でバージョンアップしています。

  1. IntelliJ IDEA のメインメニューから「Help」-「Check for Updates...」を選択します。

  2. IDE and Plugin Updates」ダイアログが表示されます。右下に「Update and Restart」ボタンが表示されていますので、「Update and Restart」ボタンをクリックします。

    f:id:ksby:20210101165335p:plain

  3. Plugin の update も表示されました。このまま「Update and Restart」ボタンをクリックします。

    f:id:ksby:20210101165421p:plain

  4. Patch がダウンロードされて IntelliJ IDEA が再起動します。

  5. IntelliJ IDEA が起動すると画面下部に「Indexing」のメッセージが表示されますので、終了するまで待機します。

    f:id:ksby:20210101170413p:plain

  6. IntelliJ IDEA のメインメニューから「Help」-「About」を選択し、2020.3.1 へバージョンアップされていることを確認します。

  7. clean タスク実行 → Rebuild Project 実行 → build タスクを実行して、"BUILD SUCCESSFUL" のメッセージが出力されることを確認します。

    f:id:ksby:20210101171625p:plain

  8. Project Tool Window で src/test でコンテキストメニューを表示して「More Run/Debug」-「Run 'All Tests' with Coverage」を選択し、テストが全て成功することを確認しようとしたら、No tests were found と実行されませんでした。。。 あと「More Run/Debug」の下に「Run 'All Tests' with 'Java Flight Recorder'」というメニューがありました。

    f:id:ksby:20210101171902p:plain

    No tests were found になるのは、いろいろ試してみたところ JUnit 5 のバージョンを 5.6.2 → 5.7.0 へ上げると成功するようになりました。原因は、

    • IntelliJ IDEA からテストを実行する時には JUnit 5 の junit-vintage-engine が使用されている。
    • 現在の build.gradle に記述している JUnit 5 のバージョンは 5.6.2。
    • Spring Boot の Web アプリは現在 2.3.7 にバージョンアップしており、それに伴い依存関係にある JUnit 4 のバージョンが 4.13.1 に上がっている。
    • JUnit 5 の 5.6.2 の junit-vintage-engine は依存関係にある JUnit 4 が 4.13.1 だと org.junit.platform.commons.JUnitException: Failed to parse version of junit:junit: 4.13.1 のメッセージを出力してテストを実行しないらしい。
    • IntelliJ IDEA の画面に出ているメッセージと Upgrade to JUnit 4.13.1 から何となくそう推測した。

    build.gradle の dependencyManagement block 内の記述で mavenBom("org.junit:junit-bom:5.6.2")mavenBom("org.junit:junit-bom:5.7.0") に変更した後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。

    clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、"BUILD SUCCESSFUL" のメッセージが出力されて、

    f:id:ksby:20210101204113p:plain

    Project Tool Window で src/test でコンテキストメニューを表示して「More Run/Debug」-「Run 'All Tests' with Coverage」を選択すると、テストが全て成功しました。

    f:id:ksby:20210101204701p:plain

    JUnit 4 のバージョンが上がると JUnit 5 の junit-vintage-engine で実行できなくなるのは意外でしたが、JUnit 4 がまだバージョンアップしているのも意外でした(4.13.1 がリリースされたのが Oct, 2020)。

  9. 最後にメジャーバージョンアップなので以前のバージョンの C:\Users\root\AppData\Local\JetBrains\IntelliJIdea2020.2 を削除します。

Git for Windows を 2.29.2.2 → 2.30.0 へバージョンアップする

Git for Windows の 2.30.0 がリリースされていたのでバージョンアップします。

  1. https://gitforwindows.org/ の「Download」ボタンをクリックして Git-2.30.0-64-bit.exe をダウンロードします。

  2. Git-2.30.0-64-bit.exe を実行します。

  3. 「Git 2.30.0 Setup」ダイアログが表示されます。インストーラーの画面を一通り見たいので「Only show new options」のチェックを外してから [Next >] ボタンをクリックします。

  4. 「Select Components」画面が表示されます。「Git LFS(Large File Support)」だけチェックした状態で [Next >]ボタンをクリックします。

  5. 「Choosing the default editor used by Git」画面が表示されます。「Use Vim (the ubiquitous text editor) as Git's default editor」が選択された状態で [Next >]ボタンをクリックします。

  6. 「Adjusting the name of the initial branch in new repositories」画面が表示されます。「Let Git decide」が選択されていることを確認後、[Next >]ボタンをクリックします。

  7. 「Adjusting your PATH environment」画面が表示されます。中央の「Git from the command line and also from 3rd-party software」が選択されていることを確認後、[Next >]ボタンをクリックします。

  8. 「Choosing HTTPS transport backend」画面が表示されます。「Use the OpenSSL library」が選択されていることを確認後、[Next >]ボタンをクリックします。

  9. 「Configuring the line ending conversions」画面が表示されます。一番上の「Checkout Windows-style, commit Unix-style line endings」が選択されていることを確認した後、[Next >]ボタンをクリックします。

  10. 「Configuring the terminal emulator to use with Git Bash」画面が表示されます。「Use Windows'default console window」が選択されていることを確認した後、[Next >]ボタンをクリックします。

  11. 「Choose the default behavior of git pull」画面が表示されます。「Default (fast-forward or merge)」が選択されていることを確認した後、[Next >]ボタンをクリックします。

  12. 「Choose a credential helper」画面が表示されます。「None」が選択されていることを確認した後、[Next >]ボタンをクリックします。

  13. 「Configuring extra options」画面が表示されます。「Enable file system caching」だけがチェックされていることを確認した後、[Next >]ボタンをクリックします。

  14. 「Configuring experimental options」画面が表示されます。何もチェックせずに [Install]ボタンをクリックします。

  15. インストールが完了すると「Completing the Git Setup Wizard」のメッセージが表示された画面が表示されます。中央の「View Release Notes」のチェックを外した後、[Next >]ボタンをクリックしてインストーラーを終了します。

  16. コマンドプロンプトを起動して git --version を実行し、git のバージョンが git version 2.30.0.windows.1 になっていることを確認します。

    f:id:ksby:20210101214440p:plain

  17. 特に問題はないようですので、2.30.0 で作業を進めたいと思います。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( 感想 )

記事一覧はこちらです。

8月に完了させるつもりでしたが、Docker image のバージョンアップがうまく出来ず 12月までかかってしまいました。。。 Spring Boot はもう 2.4.1 までリリースされているにもかかわらず。Spring Boot のバージョンアップは Spring Boot 自体は Release Notes を見ればほとんど問題はないのですが、使用しているモジュールやツールのバージョンアップの方が大変なのかもしれません。

  • 今回も大きな変更はなく、Spring Boot のバージョンアップ自体は Spring Boot 2.3 Release Notes を見れば容易に出来ました。このバージョンから Kubernetes 向けの機能が少しずつ入ってきている印象です。

  • Checkstyle はこれまで google_checks.xml をベースに一部修正して使っていましたが、Java 14 向けの定義も入ってきて Java 11 で開発していると削除しないといけない箇所が出てきて少し分かりにくくなりました。

  • SpotBugs は beta が取れて設定もすっきりして使いやすくなりました。

  • 今回一番苦労したのが Docker image のバージョンアップでした。

    • pgAdmin 4 でログインができなくなり、ソースを確認しないと原因が分かりませんでした。
    • Redis は 5 → 6 へのメジャーバージョンアップでしたが、大きな機能追加が行われているわりにはバージョン番号を上げるだけで大丈夫でした。
    • 一番苦労したのが RabbitMQ です。メジャーバージョンアップでもマイナーバージョンアップでもないのに。。。 環境変数 RABBITMQ_ERLANG_COOKIE の使用が deprecated になったので .erlang.cookie file に変えようとしましたが、RabbitMQ が permission をチェックしていて、かつ Docker image で .erlang.cookie を配置するディレクトリを VOLUME コマンドで指定されている場合に permission を変更する方法が全然分かりませんでした。
    • Grafana もメジャーバージョンアップでしたが、こちらもバージョン番号を上げるだけで済みました。
  • Doma 2 が結構大きく変わりました。これまでそんな大きな変更は入らないモジュールという印象でしたが、今回見た限りでも以下の点が追加・変更されています。

    • build.gradle の記述の仕方が変わりました。
    • ログの出力で SLF4J がサポートされました。
    • Doma-Gen がなくなって doma-codegen-plugin に変わりました。
    • Criteria API が追加されました。
  • Build OCI images with Cloud Native Buildpacks が便利ですね。Docker image の生成はこれで十分という印象です。Web アプリをコンテナで運用することが増えたので、今回のバージョンアップはこれが一番うれしい機能追加なのかもしれません。

次は 2.4 へのバージョンアップかな、と思いつつ別のことを書くかもしれません。あと来年は JDK 17、Gradle 7、Spock 2.0(Groovy も 3系へ)あたりのバージョンアップがあるのか。。。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その19 )( Docker で複数の Tomcat を起動して動作確認する )

概要

記事一覧はこちらです。

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

  • 今回の手順で確認できるのは以下の内容です。
    • Build OCI images with Cloud Native Buildpacks の機能で作成した Docker image で Web アプリを実行して動作確認します。
    • 今回はいろいろ苦労したので、動作確認時の手順を docker-compose up -d から一通り書いてみます。

参照したサイト・書籍

目次

  1. docker-compose up -d を実行する
  2. clean タスク実行 → Rebuild Project 実行 → build タスクを実行する
  3. bootBuildImage タスクを実行する
  4. Docker で複数の Tomcat を起動して動作確認する

手順

docker-compose up -d を実行する

docker-compose up -d を実行します。

f:id:ksby:20201230085246p:plain

rabbitmq-create-user コンテナに以下の画像の赤枠の Adding user "rabbitmq" ... 等のメッセージが出力されることを確認します。これまで何度も実行しましたが、たまに失敗することがありました。

f:id:ksby:20201230085401p:plain

http://localhost:1936/haproxy?stats にアクセスして全て緑になっていることを確認します。

f:id:ksby:20201230085629p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行する

clean タスク実行 → Rebuild Project 実行 → build タスクを実行して BUILD SUCCESSFUL のメッセージが出力されることを確認します。

f:id:ksby:20201230090319p:plain

bootBuildImage タスクを実行する

bootBuildImage タスクを実行して Successfully built image 'docker.io/library/ksbysample-webapp-lending:2.3.7-RELEASE'BUILD SUCCESSFUL のメッセージが出力されることを確認します。

f:id:ksby:20201230090801p:plain

Docker で複数の Tomcat を起動して動作確認する

docker-compose.app.yml で「bootBuildImage で生成した docker image を利用する場合の設定」の方の app コンテナの設定が有効になっていることを確認してから、

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

..........

以下のコマンドを実行してメールサーバ、Web アプリを起動します。

  • docker-compose -f docker-compose.mail.yml up -d
  • docker-compose -f docker-compose.app.yml --compatibility up -d

f:id:ksby:20201230090518p:plain f:id:ksby:20201230091031p:plain

app コンテナの1つのログを見て Started Application in ... seconds のログが出力されることを確認します。

f:id:ksby:20201230091207p:plain

http://localhost:8080/haproxy?stats にアクセスして全て緑になっていることを確認します。

f:id:ksby:20201230091347p:plain

以下の手順で動作確認します ( 画面キャプチャは省略します )。

  • ブラウザを起動して http://localhost:8080/ にアクセスしてログイン画面を表示します。tanaka.taro@sample.com / taro でログインします。
  • 検索対象図書館登録画面が表示されます。"東京都" で検索した後、一覧表示されている図書館から「国立国会図書館東京本館」を選択します。
  • ログアウトします。
  • ログイン画面に戻るので suzuki.hanako@test.co.jp / hanako でログインします。
  • 貸出希望書籍 CSV ファイルアップロード画面が表示されます。以下の内容が記述された CSV ファイルをアップロードします。

    "ISBN","書名"
    "978-4-7741-6366-6","GitHub実践入門"
    "978-4-7741-5377-3","JUnit実践入門"
    "978-4-7973-8014-9","Java最強リファレンス"
    "978-4-7973-4778-4","アジャイルソフトウェア開発の奥義"
    "978-4-87311-704-1","Javaによる関数型プログラミング"

  • 「貸出状況を確認しました」のメールが送信されるので、メールに記述されている URL にアクセスします。
  • 貸出申請画面が表示されます。3冊程「申請する」を選択して申請します。
  • ログアウトします。
  • 「貸出申請がありました」のメールが送信されるので、メールに記述されている URL にアクセスします。ログイン画面が表示されるので、tanaka.taro@sample.com / taro でログインします。
  • 貸出承認画面が表示されます。「承認」あるいは「却下」を選択して確定させます。
  • ログアウトします。
  • 「貸出申請が承認・却下されました」のメールが送信されるので、メールに記述されている URL にアクセスします。ログイン画面が表示されるので、suzuki.hanako@test.co.jp / hanako でログインします。
  • 貸出申請結果確認画面が表示されるので内容を確認します。

動作確認は特に問題ありませんでした。

以下のコマンドを実行してコンテナを停止します。

  • docker-compose -f docker-compose.app.yml --compatibility down
  • docker-compose -f docker-compose.mail.yml down
  • docker-compose down

履歴

2020/12/30
初版発行。

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
初版発行。

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

概要

記事一覧はこちらです。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その16 )( ValuesHelper クラスで guava の ClassPath を使用しないよう変更する ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Alpine Linux ベースの app コンテナで Web アプリを実行すると日本語のメッセージが表示されないことに気づいたので、その問題を解消します。

参照したサイト・書籍

  1. Dockerコンテナ上でJavaプログラムを動かすときにLANG環境変数を設定すると日本語のファイル名が文字化けする問題
    https://qiita.com/Targityen/items/f921c95e684810d7087f

  2. alpineベースのDockerイメージだとlocaledefが動かない
    https://hacknote.jp/archives/26886/

  3. teikoku-penguin / alpine-ja_JP/ Dockerfile
    https://github.com/teikoku-penguin/alpine-ja_JP/blob/master/Dockerfile

  4. sgerrand / alpine-pkg-glibc
    https://github.com/sgerrand/alpine-pkg-glibc

  5. AdoptOpenJDK / openjdk-docker
    https://github.com/AdoptOpenJDK/openjdk-docker

  6. How to set locale in Docker Alpine?
    https://stackoverflow.com/questions/49042223/how-to-set-locale-in-docker-alpine

  7. ロケール環境変数」の種類と優先順位まとめ【LC_ALL・LC_*・LANG・LANGUAGE】
    https://linuxfan.info/locale-variables

目次

  1. Docker で Web アプリを実行すると日本語のメッセージが表示されない
  2. app コンテナの Alpine Linux に sgerrand/alpine-pkg-glibc をインストールして ja_JP.utf8 を使用可能にする

手順

Docker で Web アプリを実行すると日本語のメッセージが表示されない

動作確認をしていて気づいたのですが、IntelliJ IDEA から Web アプリを実行した時にはログイン画面から何も入力せずに「ログイン」ボタンを押すと日本語のメッセージが表示されますが、

f:id:ksby:20201228163523p:plain

Docker 上で adoptopenjdk/openjdk11:jdk-11.0.9.1_1-alpine-slim ベースのコンテナから Web アプリを実行した時には日本語のメッセージが表示されません。

f:id:ksby:20201228163929p:plain

Dockerコンテナ上でJavaプログラムを動かすときにLANG環境変数を設定すると日本語のファイル名が文字化けする問題 の記事によると日本語ロケールが登録されていないためらしいのですが、docker/app/docker-entrypoint.sh に locale -a を追加して実行しても、

#!/bin/sh
# 改行コードを LF にすること。LF でないと実行されない。

export JAVA_OPTS="-Xms1024m -Xmx1024m -XX:MaxMetaspaceSize=384m"

locale -a
exec java $JAVA_OPTS \
          -Djava.security.egd=file:/dev/./urandom \
          -Dspring.profiles.active=product \
          -Dserver.tomcat.basedir=/ \
          -Dlogging.appender=CONSOLE \
          -jar /app.jar

locale: not found のメッセージが表示されて、指定可能なロケールを確認することが出来ませんでした。

f:id:ksby:20201228164455p:plain

app コンテナの Alpine Linux に sgerrand/alpine-pkg-glibc をインストールして ja_JP.utf8 を使用可能にする

alpineベースのDockerイメージだとlocaledefが動かない の記事によると glibc 関連らしく、もう少し調べていたら teikoku-penguin/alpine-ja_JP/Dockerfile を見つけました。

docker/app/Dockerfile を以下のように変更します。

FROM adoptopenjdk/openjdk11:jdk-11.0.9.1_1-alpine-slim

RUN apk update && \
    apk upgrade; \
    wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub; \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.31-r0/glibc-2.31-r0.apk; \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.31-r0/glibc-bin-2.31-r0.apk; \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.31-r0/glibc-i18n-2.31-r0.apk; \
    apk add --no-cache --update \
    bash \
    tzdata \
    glibc-2.31-r0.apk \
    glibc-bin-2.31-r0.apk \
    glibc-i18n-2.31-r0.apk; \
    rm glibc-2.31-r0.apk glibc-bin-2.31-r0.apk glibc-i18n-2.31-r0.apk

RUN /usr/glibc-compat/bin/localedef -i ja_JP -f UTF-8 ja_JP.UTF-8

ENV TZ Asia/Tokyo
ENV LANG ja_JP.utf8
ENV LC_ALL ja_JP.utf8

VOLUME /tmp
EXPOSE 8080
ENTRYPOINT ["docker-entrypoint.sh"]
  • RUN apk add --no-cache tzdataRUN apk update && ... rm glibc-2.31-r0.apk glibc-bin-2.31-r0.apk glibc-i18n-2.31-r0.apk に変更します。openjdk-docker/11/jdk/alpine/Dockerfile.hotspot.releases.slim を見ると glibc のバージョンが 2.31-r0 でしたので apk update ... のコマンド内で指定する glibc のバージョンを 2.31-r0 に変更します。
  • この方法でインストールした後 locale -a コマンドを実行して表示されたロケールja_JP.utf8 でしたので、ENV LANG="ja_JP.UTF-8"ENV LANG ja_JP.utf8 に変更します。
  • 環境変数 LANG を指定しただけでは日本語メッセージが表示されない問題が解消されないため ENV LC_ALL ja_JP.utf8 を追加します。

docker/app/docker-entrypoint.sh にロケール一覧を確認するために /usr/glibc-compat/bin/locale -a を追加します。

#!/bin/sh
# 改行コードを LF にすること。LF でないと実行されない。

export JAVA_OPTS="-Xms1024m -Xmx1024m -XX:MaxMetaspaceSize=384m"

/usr/glibc-compat/bin/locale -a
exec java $JAVA_OPTS \
          -Djava.security.egd=file:/dev/./urandom \
          -Dspring.profiles.active=product \
          -Dserver.tomcat.basedir=/ \
          -Dlogging.appender=CONSOLE \
          -jar /app.jar

docker-compose -f docker-compose.app.yml --compatibility build --no-cache コマンドを実行して Docker Image を作り直します。

f:id:ksby:20201228171500p:plain f:id:ksby:20201228171641p:plain f:id:ksby:20201228171738p:plain

docker-compose -f docker-compose.app.yml --compatibility up -d コマンドで app コンテナを実行します。/usr/glibc-compat/bin/locale -a コマンドが実行されると ja_JP.utf8 が表示されます。

f:id:ksby:20201228172510p:plain

ログイン画面から何も入力せずに「ログイン」ボタンを押すと日本語のメッセージが表示されました。

f:id:ksby:20201228172725p:plain

履歴

2020/12/28
初版発行。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( 番外編 )( IntelliJ IDEA の docToolchain/diagrams.net-intellij-plugin を追加する )

概要

記事一覧はこちらです。

Twitter で draw.io を直接利用できる IntelliJ IDEA の Plugin がリリースされたと見かけました。 まだ This plugin is still an early version and experimental. とのことですが、欲しいと思っていた Plugin なのでインストールしてみます。

参照したサイト・書籍

  1. docToolchain / diagrams.net-intellij-plugin
    https://github.com/docToolchain/diagrams.net-intellij-plugin

  2. Draw.io Integration for IntelliJ
    https://drawio-intellij-plugin.netlify.app/

目次

  1. docToolchain/diagrams.net-intellij-plugin を追加する

手順

docToolchain/diagrams.net-intellij-plugin を追加する

IntelliJ IDEA の Plugin の画面から diagrams.net-intellij-plugin で検索してインストールします。

f:id:ksby:20201226222041p:plain

.sample/sample.drawio を作成して開くと VS Code の Extension と同じように draw.io の画面が表示されます。

f:id:ksby:20201226230430p:plain

AWS のアイコンも使用でき、使い勝手も VS Code の Extension と変わらないようです。VS Code と違い IntelliJ IDEA らしく保存は自動で行われます。

f:id:ksby:20201226231132p:plain

.sample/sample.drawio を VS Code で開くと同じように表示されました。

f:id:ksby:20201226231443p:plain

Import/Export や Save の機能はまだでした(左が IntelliJ IDEA、右が VS Code)。

f:id:ksby:20201226231709p:plainf:id:ksby:20201226231806p:plain

未実装の機能がありますが、結構良さそうです。使っていきたいと思います。

またどうやって作るのかソースを見たところ、Kotlin で書かれていました。テストは Groovy で Spock でしたが。そうか、そういう組み合わせもあるのか。

履歴

2020/12/26
初版発行。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その16 )( ValuesHelper クラスで guava の ClassPath を使用しないよう変更する )

概要

記事一覧はこちらです。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その15 )( Doma 2 を 2.26.0 → 2.44.3 へバージョンアップする+domaGen タスクを doma-codegen-plugin を利用したものに作り直す ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • ksbysample.webapp.lending.values.ValuesHelper クラスのコンストラクタで values パッケージの下のクラス一覧を取得してフィールドの Map オブジェクトに保存しており、現在 guava の ClassPath クラスを利用しています。
    • Spring のクラスでも実現できるのではないかと思い以前から変更方法を調べていたのですが、その方法を見つけたので変更します。Web アプリの中で com.google.common.collect.Multiset を使用している箇所があるので guava を依存関係から削除することはできませんが、values パッケージを利用するだけなら guava を依存関係に追加する必要がなくります。

参照したサイト・書籍

目次

  1. ksbysample.webapp.lending.values.ValuesHelper クラスで guava の ClassPath を使用しないよう変更する

手順

ksbysample.webapp.lending.values.ValuesHelper クラスで guava の ClassPath を使用しないよう変更する

現在 guava の ClassPath を使用して以下のように実装していますが、

import com.google.common.reflect.ClassPath;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * ???
 */
@Component("vh")
public final class ValuesHelper {

    private final Map<String, String> valuesObjList;

    private ValuesHelper(@Value("${valueshelper.classpath.prefix:}") String classpathPrefix) throws IOException {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        valuesObjList = ClassPath.from(loader)
                .getTopLevelClassesRecursive(classpathPrefix + this.getClass().getPackage().getName())
                .stream()
                .filter(classInfo -> {
                    try {
                        Class<?> clazz = Class.forName(classInfo.getName().replace(classpathPrefix, ""));
                        return !clazz.equals(Values.class) && Values.class.isAssignableFrom(clazz);
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                })
                .collect(Collectors.toMap(classInfo -> classInfo.getSimpleName()
                        , classInfo -> classInfo.getName().replace(classpathPrefix, "")));
    }

    ..........

Can you find all classes in a package using reflection? の 104 の Spring のコードを参考に以下のように変更します。@ComponentScan アノテーションがあるので Spring のクラスで実現できるはずと思っていましたが、ClassPathScanningCandidateComponentProvider クラスを使えばできることが分かりました。

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.RegexPatternTypeFilter;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * ???
 */
@Component("vh")
public final class ValuesHelper {

    private final Map<String, String> valuesObjList;

    private ValuesHelper() {
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*")));
        Set<BeanDefinition> beans = provider.findCandidateComponents(this.getClass().getPackage().getName());
        valuesObjList = beans.stream()
                .map(bean -> {
                    try {
                        return Class.forName(bean.getBeanClassName());
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                })
                .filter(clazz -> !clazz.equals(Values.class) && Values.class.isAssignableFrom(clazz))
                .collect(Collectors.toMap(clazz -> clazz.getSimpleName(), clazz -> clazz.getName()));
    }

    ..........

コンストラクタの引数に渡していた @Value("${valueshelper.classpath.prefix:}") String classpathPrefix を削除したので、以下の設定ファイルの項目を削除します。

  • src/main/resources/application.properties の valueshelper.classpath.prefix=
  • src/main/resources/application-product.properties の valueshelper.classpath.prefix=BOOT-INF.classes.

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20201226195331p:plain

IntelliJ IDEA から Web アプリを起動しても Docker から Web アプリを起動しても動作には問題ありませんでした。

履歴

2020/12/26
初版発行。