Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Java × distroless で 軽量なコンテナイメージを / Java on Dist...
Search
Daisuke Garaike
May 29, 2026
Programming
580
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
https://jjugccc2026s.sessionize.com/session/1172902
Daisuke Garaike
May 29, 2026
More Decks by Daisuke Garaike
See All by Daisuke Garaike
立川で超かぐや姫!について話したい / Talking Cosmic Princess Kaguya! in Tachikawa
contour_gara
1
360
AR グラス + ミニ PC で実現する新しいモバイル環境
contour_gara
0
340
TDD 実践ミニトーク
contour_gara
1
420
Spring Boot と AWS S3 を使ったアプリケーションのテスト
contour_gara
0
150
ノート PC に Linux 入れてみたけど結構良かった
contour_gara
0
3.6k
JUnit5 から Kotest へ
contour_gara
0
210
社外での学びを社内に還元したい
contour_gara
1
560
2 週間で Twitter Bot を作ってみた
contour_gara
0
1.3k
Database Rider を用いたデータベーステスト
contour_gara
0
480
Other Decks in Programming
See All in Programming
代数的データ型って何が嬉しいの? #frontend_phpcon_do
kajitack
8
3.9k
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
12
4.6k
「なぜそう決めたのか」を残し続ける仕組み ― Notion AI カスタムエージェント × Slack連携による設計判断の自動記録 - NIKKEI Tech Talk #47
niftycorp
PRO
0
250
なぜ型を書くのか? TSKaigi2026で改めて考える #tskaigi_smarthr
kajitack
0
180
Performance Engineering for Everyone
elenatanasoiu
0
250
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
570
Signal Forms: Details & Live Coding @enterJS 2026 in Mannheim
manfredsteyer
PRO
0
210
AI がコードを書く時代における新卒エンジニアの仕事風景 (2026) / New Graduate Engineers in the Era of AI Coding (2026)
sushichan044
0
190
Agentic UI
manfredsteyer
PRO
0
220
技術的負債解消で開発者の未来を開く- AIの力でコード刷新
kmd2kmd
0
140
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
340
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
3
810
Featured
See All Featured
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
180
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
KATA
mclloyd
PRO
35
15k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
760
Into the Great Unknown - MozCon
thekraken
41
2.6k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
320
Joys of Absence: A Defence of Solitary Play
codingconduct
1
410
Designing for Timeless Needs
cassininazir
1
270
Six Lessons from altMBA
skipperchong
29
4.3k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
Transcript
Java × distroless で 軽量なコンテナイメージを 2026-05-30 JJUG CCC 2026 Spring
Daisuke Garaike
プロポーザルの変更点 • Java のバージョンを変更 ◦ 21 -> 25 2
Daisuke Garaike • Product Engineer ◦ ハンディ株式会社 ◦ Backend ▪
Kotlin, Java • サーバーサイド Kotlin, アジャイル, 自動テスト, プロダクト開発 3
アジェンダ 1. Distroless を使う モチベーション 2. Java アプリを Distroless で
動かす 3. コンテナイメージのサイズと 起動速度の比較 4. Java アプリを Distroless で 動かす際にやってほしいこと 4
Distroless を使うモチベーション 5
なぜコンテナアプリケーション • The Twelve-Factor App ◦ アプリを環境から切り離す ◦ アプリを入れ替え可能に •
ローカルでもクラウドでも 同じものが動く 6
JVM のイメージは重い • docker イメージのサイズ ◦ amazoncorretto: 132.64 MB ◦
eclipse-temurin: 143.42 MB ◦ 参考: ▪ debian: 47.03 MB • これらにアプリケーションが載る • 環境構築時に待たされる • 新規開発時に待たされる • Write Once, Run Anywhere と被っているから? 7
軽量イメージを使って問題解決 • debian-slim: 28.4 MB • Alpine Linux: 3.69 MB
• Distroless: 10.99 MB ◦ Google 管理 ◦ シェルがないため攻撃に強い ◦ Java で Distroless を使っている話を あまり聞かないので今回のテーマに 8
Java アプリを Distroless で動かす 9
サンプルアプリについて • Kotlin, Gradle, Java25, Spring Boot 4.0.6 • ルートエンドポイントに
GET すると "Hello World!" が返る 10
corretto # syntax=docker/dockerfile:1 FROM amazoncorretto:25.0.3-al2023 WORKDIR /deployments ARG JAR_FILE=build/libs/app.jar COPY
${JAR_FILE} app.jar ENTRYPOINT ["java", "-jar", "app.jar"] 11
Distroless # syntax=docker/dockerfile:1 FROM gcr.io/distroless/java25-debian13:nonroot WORKDIR /deployments ARG JAR_FILE=build/libs/app.jar COPY
--chown=nonroot:nonroot ${JAR_FILE} app.jar CMD ["app.jar"] 12 • JVM は Temurin • Entrypoint に `java -jar` が 指定されている
Distroless x カスタム JRE # syntax=docker/dockerfile:1 FROM amazoncorretto:25.0.3-al2023 AS build
WORKDIR /jlink RUN jlink \ --verbose \ --compress=2 \ --strip-java-debug-attributes \ --no-header-files \ --no-man-pages \ --add-modules [依存モジュール] \ --output jre-min 13 • アプリ実行に必要なモジュール のみを集めた JRE • Spring Boot アプリの 依存モジュールの調べ方は 割愛 FROM gcr.io/distroless/java-base-debian13:nonroot WORKDIR /deployments COPY --from=build --chown=nonroot:nonroot /jlink/jre-min /opt/jre-min ENV JAVA_HOME=/opt/jre-min ENV PATH=$JAVA_HOME/bin:$PATH ARG JAR_FILE=build/libs/app.jar COPY ${JAR_FILE} app.jar ENTRYPOINT ["java", "-jar", "app.jar"]
Buildpacks x Distroless x カスタム JRE plugins { alias(libs.plugins.spring.boot) }
tasks.bootBuildImage { runImage = "gcr.io/distroless/java-base-debian13:nonroot" imageName = "distroless-jvm-examples-distroless-custom-jre-buildpack" environment = mapOf( "BP_JVM_JLINK_ENABLED" to "true", "BP_JVM_JLINK_ARGS" to "--add-modules [依存モジュール]", ) } 14 [versions] spring-boot = "4.0.6" [plugins] spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" }
コンテナイメージのサイズと 起動速度の比較 15
サイズの比較 16 イメージ 圧縮後サイズ corretto 265.43 MB distroless 94.62 MB
distroless-custom-jre 72.79 MB distroless-custom-jre-buildpack 87.92 MB
コンテナ実行環境での起動時間の比較 • コンテナ起動時間とイメージサイズ ◦ pull 時間 + アプリ起動時間 = コンテナ起動時間
• 実験手法 ◦ ECR + ECS Express ◦ デプロイ方式: カナリアデプロイ ▪ ベイク時間: 合計 6 分 ◦ 102 回再起動 17 引用: DevelopersIO, Classmethod, ECS Express Mode でデプロイにかかる時間を可能な限り短縮する, https://dev.classmethod.jp/articles/ecs-experss-reduce-deployment-time/
コンテナ実行環境での起動時間の比較 • 結果 18 秒 corretto Distroless Buildpacks x Distroless
x カスタム JRE Distroless x カスタム JRE • Dockerfile 形式同士: 軽量なほど起動時間が速い • サイズだけが起動時間に影響している訳ではない
Java アプリを Distroless で 動かす際にやってほしいこと 19
ローカルから docker で起動しておく • ローカルでもクラウドでも同じものを実行する ◦ The Twelve Factor App
• compose.yaml ◦ アプリ起動に必要な環境変数もまとめられる • 起動方法 ◦ Jar ファイルのビルド: gradle build ◦ コンテナ実行: docker compose up --build 20
コンテナレベルのブラックボックステスト • アプリの異常だけでなく コンテナの異常を検知できる • プラグインで自動化 ◦ テスト実行前: compose up
◦ テスト実行後: compose down 21 [versions] docker-compose = "0.17.21" [plugins] docker-compose = { id = "com.avast.gradle.docker-compose", version.ref = "docker-compose" } plugins { alias(libs.plugins.docker.compose) } dockerCompose { useComposeFiles = listOf("../compose.yaml") } tasks.test { useJUnitPlatform() mustRunAfter("composeUp") } tasks.composeDown { mustRunAfter("test") } tasks.register("integrationTest") { dependsOn("composeUp") dependsOn("test") dependsOn("composeDown") }
リモートデバッグ • ローカルでコンテナを実行してもデバッグが可能 • JRE に jdk.jdwp.agent を追加 • 5005
ポートの解放 • 環境変数 JAVA_TOOL_OPTIONS 22 services: distroless-custom-jre: build: context: ./app dockerfile: Dockerfile_distroless_custom_jre ports: - "8083:8080" - "5005:5005" environment: JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
docker compose のヘルスチェックが難しい • Dockerfile や compose.yaml のヘルスチェックは コンテナ内でコマンドを実行する •
curl がないためヘルスチェックができない • クラウドの場合は問題ないことが多いので 気にしていない 23
まとめ 24
まとめ • イメージサイズの軽量化は、これらの時間短縮につながる ◦ ローカル環境での初回 pull ◦ コンテナレジストリへの初回 push ◦
コンテナ実行環境での起動時間 • コンテナ起動時間の短縮は、 サイズだけではなくコンテナ構造も影響する • コンテナイメージを工夫する場合、 常にコンテナでアプリを起動するようにする 25
アンケートの回答お願いします 全体アンケート 26 セッション アンケート