Skip to content

Commit 9f83afb

Browse files
feat: migrate all JVM services to JDK 21 runtime
Merges PR #1240 - adds JDK 21 base images with CDS pre-dumps for 26 Spring Boot 3.x services and a JDK 8→21 hybrid image for egov-user, fixing cgroup v2 CPU detection bug (JDK-8281181) on kernel 6.8+. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2 parents 9c9e295 + affb45a commit 9f83afb

7 files changed

Lines changed: 219 additions & 37 deletions

File tree

build/build-config.yml

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,13 @@ config:
8989
build:
9090
- work-dir: "core-services/egov-accesscontrol"
9191
image-name: "egov-accesscontrol"
92-
dockerfile: "build/maven/Dockerfile"
92+
dockerfile: "build/maven-jdk21/Dockerfile"
9393
# Core Services
9494
- name: "builds/Digit-Core/core-services/audit-service"
9595
build:
9696
- work-dir: "core-services/audit-service"
9797
image-name: "audit-service"
98-
dockerfile: "build/maven/Dockerfile"
98+
dockerfile: "build/maven-jdk21/Dockerfile"
9999
- work-dir: "core-services/audit-service/src/main/resources/db"
100100
image-name: "audit-service-db"
101101
- name: "builds/Digit-Core/core-services/egov-common-masters"
@@ -118,103 +118,103 @@ config:
118118
build:
119119
- work-dir: "core-services/egov-enc-service"
120120
image-name: "egov-enc-service"
121-
dockerfile: "build/maven/Dockerfile"
121+
dockerfile: "build/maven-jdk21/Dockerfile"
122122
- work-dir: "core-services/egov-enc-service/src/main/resources/db"
123123
image-name: "egov-enc-service-db"
124124

125125
- name: "builds/Digit-Core/core-services/egov-filestore"
126126
build:
127127
- work-dir: "core-services/egov-filestore"
128128
image-name: "egov-filestore"
129-
dockerfile: "build/maven/Dockerfile"
129+
dockerfile: "build/maven-jdk21/Dockerfile"
130130
- work-dir: "core-services/egov-filestore/src/main/resources/db"
131131
image-name: "egov-filestore-db"
132132

133133
- name: "builds/Digit-Core/core-services/egov-idgen"
134134
build:
135135
- work-dir: "core-services/egov-idgen"
136136
image-name: "egov-idgen"
137-
dockerfile: "build/maven/Dockerfile"
137+
dockerfile: "build/maven-jdk21/Dockerfile"
138138
- work-dir: "core-services/egov-idgen/src/main/resources/db"
139139
image-name: "egov-idgen-db"
140140

141141
- name: "builds/Digit-Core/core-services/egov-indexer"
142142
build:
143143
- work-dir: "core-services/egov-indexer"
144144
image-name: "egov-indexer"
145-
dockerfile: "build/maven/Dockerfile"
145+
dockerfile: "build/maven-jdk21/Dockerfile"
146146
- work-dir: "core-services/egov-indexer/src/main/resources/db"
147147
image-name: "egov-indexer-db"
148148

149149
- name: "builds/Digit-Core/core-services/egov-localization"
150150
build:
151151
- work-dir: "core-services/egov-localization"
152152
image-name: "egov-localization"
153-
dockerfile: "build/maven/Dockerfile"
153+
dockerfile: "build/maven-jdk21/Dockerfile"
154154
- work-dir: "core-services/egov-localization/src/main/resources/db"
155155
image-name: "egov-localization-db"
156156

157157
- name: "builds/Digit-Core/core-services/egov-location"
158158
build:
159159
- work-dir: "core-services/egov-location"
160160
image-name: "egov-location"
161-
dockerfile: "build/maven/Dockerfile"
161+
dockerfile: "build/maven-jdk21/Dockerfile"
162162
- work-dir: "core-services/egov-location/src/main/resources/db"
163163
image-name: "egov-location-db"
164164

165165
- name: "builds/Digit-Core/core-services/boundary-service"
166166
build:
167167
- work-dir: "core-services/boundary-service"
168168
image-name: "boundary-service"
169-
dockerfile: "build/maven/Dockerfile"
169+
dockerfile: "build/maven-jdk21/Dockerfile"
170170
- work-dir: "core-services/boundary-service/src/main/resources/db"
171171
image-name: "boundary-service-db"
172172

173173
- name: "builds/Digit-Core/core-services/egov-mdms-service"
174174
build:
175175
- work-dir: "core-services/egov-mdms-service"
176176
image-name: "egov-mdms-service"
177-
dockerfile: "build/maven/Dockerfile"
177+
dockerfile: "build/maven-jdk21/Dockerfile"
178178

179179
- name: "builds/Digit-Core/core-services/mdms-v2"
180180
build:
181181
- work-dir: "core-services/mdms-v2"
182182
image-name: "mdms-v2"
183-
dockerfile: "build/maven/Dockerfile"
183+
dockerfile: "build/maven-jdk21/Dockerfile"
184184
- work-dir: "core-services/mdms-v2/src/main/resources/db"
185185
image-name: "mdms-v2-db"
186186

187187
- name: "builds/Digit-Core/core-services/egov-notification-mail"
188188
build:
189189
- work-dir: "core-services/egov-notification-mail"
190190
image-name: "egov-notification-mail"
191-
dockerfile: "build/maven/Dockerfile"
191+
dockerfile: "build/maven-jdk21/Dockerfile"
192192

193193
- name: "builds/Digit-Core/core-services/egov-notification-sms"
194194
build:
195195
- work-dir: "core-services/egov-notification-sms"
196196
image-name: "egov-notification-sms"
197-
dockerfile: "build/maven/Dockerfile"
197+
dockerfile: "build/maven-jdk21/Dockerfile"
198198

199199
- name: "builds/Digit-Core/core-services/egov-otp"
200200
build:
201201
- work-dir: "core-services/egov-otp"
202202
image-name: "egov-otp"
203-
dockerfile: "build/maven/Dockerfile"
203+
dockerfile: "build/maven-jdk21/Dockerfile"
204204
- work-dir: "core-services/egov-otp/src/main/resources/db"
205205
image-name: "egov-otp-db"
206206

207207
- name: "builds/Digit-Core/core-services/egov-persister"
208208
build:
209209
- work-dir: "core-services/egov-persister"
210210
image-name: "egov-persister"
211-
dockerfile: "build/maven/Dockerfile"
211+
dockerfile: "build/maven-jdk21/Dockerfile"
212212

213213
- name: "builds/Digit-Core/core-services/egov-pg-service"
214214
build:
215215
- work-dir: "core-services/egov-pg-service"
216216
image-name: "egov-pg-service"
217-
dockerfile: "build/maven/Dockerfile"
217+
dockerfile: "build/maven-jdk21/Dockerfile"
218218
- work-dir: "core-services/egov-pg-service/src/main/resources/db"
219219
image-name: "egov-pg-service-db"
220220

@@ -234,23 +234,23 @@ config:
234234
build:
235235
- work-dir: "core-services/egov-user"
236236
image-name: "egov-user"
237-
dockerfile: "build/maven-java8/Dockerfile"
237+
dockerfile: "build/maven-java8-jdk21/Dockerfile"
238238
- work-dir: "core-services/egov-user/src/main/resources/db"
239239
image-name: "egov-user-db"
240240

241241
- name: "builds/Digit-Core/core-services/egov-user-event"
242242
build:
243243
- work-dir: "core-services/egov-user-event"
244244
image-name: "egov-user-event"
245-
dockerfile: "build/maven/Dockerfile"
245+
dockerfile: "build/maven-jdk21/Dockerfile"
246246
- work-dir: "core-services/egov-user-event/src/main/resources/db"
247247
image-name: "egov-user-event-db"
248248

249249
- name: "builds/Digit-Core/core-services/egov-workflow-v2"
250250
build:
251251
- work-dir: "core-services/egov-workflow-v2"
252252
image-name: "egov-workflow-v2"
253-
dockerfile: "build/maven/Dockerfile"
253+
dockerfile: "build/maven-jdk21/Dockerfile"
254254
- work-dir: "core-services/egov-workflow-v2/src/main/resources/db"
255255
image-name: "egov-workflow-v2-db"
256256

@@ -303,7 +303,7 @@ config:
303303
build:
304304
- work-dir: "core-services/user-otp"
305305
image-name: "user-otp"
306-
dockerfile: "build/maven/Dockerfile"
306+
dockerfile: "build/maven-jdk21/Dockerfile"
307307

308308
- name: "builds/Digit-Core/core-services/zuul"
309309
build:
@@ -315,7 +315,7 @@ config:
315315
build:
316316
- work-dir: "core-services/gateway"
317317
image-name: "gateway"
318-
dockerfile: "build/maven/Dockerfile"
318+
dockerfile: "build/maven-jdk21/Dockerfile"
319319

320320
- name: "builds/Digit-Core/core-services/internal-gateway"
321321
build:
@@ -327,15 +327,15 @@ config:
327327
build:
328328
- work-dir: "core-services/internal-gateway-scg"
329329
image-name: "internal-gateway-scg"
330-
dockerfile: "build/maven/Dockerfile"
331-
330+
dockerfile: "build/maven-jdk21/Dockerfile"
331+
332332
- name: "builds/Digit-Core/core-services/egov-user-event"
333333
build:
334334
- work-dir: "core-services/egov-user-event"
335335
image-name: "egov-user-event"
336-
dockerfile: "build/maven/Dockerfile"
336+
dockerfile: "build/maven-jdk21/Dockerfile"
337337
- work-dir: "core-services/egov-user-event/src/main/resources/db"
338-
image-name: "egov-user-event-db"
338+
image-name: "egov-user-event-db"
339339

340340
- name: "builds/Digit-Core/core-services/pdf-service"
341341
build:
@@ -360,7 +360,7 @@ config:
360360
build:
361361
- work-dir: "core-services/egov-url-shortening"
362362
image-name: "egov-url-shortening"
363-
dockerfile: "build/maven/Dockerfile"
363+
dockerfile: "build/maven-jdk21/Dockerfile"
364364
- work-dir: "core-services/egov-url-shortening/src/main/resources/db"
365365
image-name: "egov-url-shortening-db"
366366

@@ -449,7 +449,7 @@ config:
449449
build:
450450
- work-dir: "accelerators/inbox"
451451
image-name: "inbox"
452-
dockerfile: "build/maven/Dockerfile"
452+
dockerfile: "build/maven-jdk21/Dockerfile"
453453

454454
- name: "builds/Digit-Core/accelerators/gateway-kubernetes-discovery"
455455
build:
@@ -460,15 +460,15 @@ config:
460460
build:
461461
- work-dir: "accelerators/pgr-services"
462462
image-name: "pgr-services"
463-
dockerfile: "build/maven/Dockerfile"
463+
dockerfile: "build/maven-jdk21/Dockerfile"
464464
- work-dir: "accelerators/pgr-services/src/main/resources/db"
465465
image-name: "pgr-services-db"
466466

467467
- name: "builds/Digit-Core/core-services/service-request"
468468
build:
469469
- work-dir: "core-services/service-request"
470470
image-name: "service-request"
471-
dockerfile: "build/maven/Dockerfile"
471+
dockerfile: "build/maven-jdk21/Dockerfile"
472472
- work-dir: "core-services/service-request/src/main/resources/db"
473473
image-name: "service-request-db"
474474

build/maven-java8-jdk21/Dockerfile

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# JDK 8→21 hybrid: compile with JDK 8, run on JDK 21.
2+
# Use this for services on Spring Boot 1.5/2.x that cannot be recompiled
3+
# for JDK 17+ but benefit from JDK 21's cgroup v2 fix and memory improvements.
4+
#
5+
# JDK 21 fixes cgroup v2 CPU detection (JDK-8281181), auto-sizes heap/threads
6+
# from container limits, and runs Java 8 bytecode natively.
7+
#
8+
# Spring Boot 1.5 needs two runtime patches for JDK 21:
9+
# 1. JAXB API + runtime (removed from JDK 11)
10+
# 2. --add-opens flags for internal JDK module access
11+
12+
# ──────────────── BUILD STAGE ────────────────
13+
FROM egovio/maven:3.9.6-amazoncorretto-8-debian AS build
14+
ARG WORK_DIR
15+
WORKDIR /app
16+
17+
COPY ${WORK_DIR}/pom.xml ./pom.xml
18+
COPY build/maven-java8-jdk21/start.sh ./start.sh
19+
COPY ${WORK_DIR}/src ./src
20+
21+
RUN mvn -B -f pom.xml package -DskipTests
22+
23+
# ──────────── JAXB PATCH STAGE ─────────────
24+
FROM eclipse-temurin:21-jdk-alpine AS patcher
25+
RUN apk add --no-cache curl
26+
WORKDIR /patch
27+
28+
COPY --from=build /app/target/*.jar ./app.jar
29+
30+
# Download JAXB API + implementation (removed from JDK 11+)
31+
RUN curl -sL -o jaxb-api.jar https://repo1.maven.org/maven2/javax/xml/bind/jaxb-api/2.3.1/jaxb-api-2.3.1.jar && \
32+
curl -sL -o javax.activation.jar https://repo1.maven.org/maven2/javax/activation/javax.activation-api/1.2.0/javax.activation-api-1.2.0.jar && \
33+
curl -sL -o jaxb-runtime.jar https://repo1.maven.org/maven2/org/glassfish/jaxb/jaxb-runtime/2.3.9/jaxb-runtime-2.3.9.jar && \
34+
curl -sL -o txw2.jar https://repo1.maven.org/maven2/org/glassfish/jaxb/txw2/2.3.9/txw2-2.3.9.jar && \
35+
curl -sL -o istack-commons-runtime.jar https://repo1.maven.org/maven2/com/sun/istack/istack-commons-runtime/3.0.12/istack-commons-runtime-3.0.12.jar && \
36+
curl -sL -o stax-ex.jar https://repo1.maven.org/maven2/org/jvnet/staxex/stax-ex/1.8.1/stax-ex-1.8.1.jar
37+
38+
# Inject JAXB jars into the fat JAR (jar uf0 preserves STORED entries)
39+
RUN mkdir -p BOOT-INF/lib && \
40+
cp jaxb-api.jar javax.activation.jar jaxb-runtime.jar txw2.jar \
41+
istack-commons-runtime.jar stax-ex.jar BOOT-INF/lib/ && \
42+
jar uf0 app.jar \
43+
BOOT-INF/lib/jaxb-api.jar \
44+
BOOT-INF/lib/javax.activation.jar \
45+
BOOT-INF/lib/jaxb-runtime.jar \
46+
BOOT-INF/lib/txw2.jar \
47+
BOOT-INF/lib/istack-commons-runtime.jar \
48+
BOOT-INF/lib/stax-ex.jar
49+
50+
# ─────────────── RUNTIME STAGE ───────────────
51+
FROM eclipse-temurin:21-jre-alpine
52+
53+
RUN apk add --no-cache dos2unix
54+
55+
WORKDIR /opt/egov
56+
57+
COPY --from=patcher /patch/app.jar /opt/egov/app.jar
58+
COPY --from=build /app/start.sh /opt/egov/start.sh
59+
60+
# CDS pre-dump: generate classlist then shared archive for faster startup.
61+
RUN timeout 30 java \
62+
--add-opens java.base/java.lang=ALL-UNNAMED \
63+
--add-opens java.base/java.lang.reflect=ALL-UNNAMED \
64+
--add-opens java.base/java.util=ALL-UNNAMED \
65+
-XX:DumpLoadedClassList=/opt/egov/app.classlist \
66+
-jar /opt/egov/app.jar 2>/dev/null; true
67+
RUN java \
68+
--add-opens java.base/java.lang=ALL-UNNAMED \
69+
--add-opens java.base/java.lang.reflect=ALL-UNNAMED \
70+
--add-opens java.base/java.util=ALL-UNNAMED \
71+
-Xshare:dump \
72+
-XX:SharedClassListFile=/opt/egov/app.classlist \
73+
-XX:SharedArchiveFile=/opt/egov/app-cds.jsa \
74+
-jar /opt/egov/app.jar 2>/dev/null; true
75+
76+
RUN dos2unix /opt/egov/start.sh && chmod +x /opt/egov/start.sh
77+
78+
CMD ["/opt/egov/start.sh"]

build/maven-java8-jdk21/start.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/sh
2+
3+
# JDK 21 auto-sizes heap from cgroup limits — no default -Xms/-Xmx needed.
4+
# Set JAVA_OPTS or JAVA_TOOL_OPTIONS via container environment if tuning is required.
5+
6+
# CDS: use shared archive if it exists (pre-baked at image build time)
7+
CDS_OPTS=""
8+
if [ -f /opt/egov/app-cds.jsa ]; then
9+
CDS_OPTS="-XX:SharedArchiveFile=/opt/egov/app-cds.jsa"
10+
fi
11+
12+
# Spring Boot 1.5 uses internal JDK APIs via reflection.
13+
# These --add-opens flags are required for JDK 21 compatibility.
14+
ADD_OPENS="--add-opens java.base/java.lang=ALL-UNNAMED"
15+
ADD_OPENS="$ADD_OPENS --add-opens java.base/java.lang.reflect=ALL-UNNAMED"
16+
ADD_OPENS="$ADD_OPENS --add-opens java.base/java.util=ALL-UNNAMED"
17+
18+
if [ x"${JAVA_ENABLE_DEBUG}" != x ] && [ "${JAVA_ENABLE_DEBUG}" != "false" ]; then
19+
java_debug_args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${JAVA_DEBUG_PORT:-5005}"
20+
fi
21+
22+
exec java ${java_debug_args} ${ADD_OPENS} ${JAVA_OPTS} ${CDS_OPTS} ${JAVA_ARGS} -jar /opt/egov/app.jar

build/maven-jdk21/Dockerfile

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# JDK 21 runtime variant of build/maven/Dockerfile.
2+
# Use this for services on Spring Boot 3.x compiled with Java 17+.
3+
# Services on Spring Boot 1.5/2.x must continue using build/maven/Dockerfile.
4+
#
5+
# JDK 21 fixes cgroup v2 CPU detection (JDK-8281181), auto-sizes heap/threads
6+
# from container limits, and runs Java 17 bytecode natively (no recompilation).
7+
8+
FROM egovio/maven:3.9.6-amazoncorretto-17 AS build
9+
ARG WORK_DIR
10+
WORKDIR /app
11+
12+
# Copy project files
13+
COPY ${WORK_DIR}/pom.xml ./pom.xml
14+
COPY build/maven-jdk21/start.sh ./start.sh
15+
COPY ${WORK_DIR}/src ./src
16+
17+
# Build the project
18+
RUN mvn -B -f /app/pom.xml package
19+
20+
# Runtime image — JDK 21 on Alpine
21+
FROM eclipse-temurin:21-jre-alpine
22+
23+
RUN apk add --no-cache dos2unix
24+
25+
WORKDIR /opt/egov
26+
27+
# Copy artifacts from the build stage
28+
COPY --from=build /app/target/*.jar /opt/egov/app.jar
29+
COPY --from=build /app/start.sh /opt/egov/start.sh
30+
31+
# CDS pre-dump: generate classlist then shared archive for faster startup.
32+
# The app will attempt to start (no DB/Kafka available) — timeout kills it
33+
# after 30s, which is enough to load all classes for the classlist.
34+
RUN timeout 30 java -XX:DumpLoadedClassList=/opt/egov/app.classlist \
35+
-jar /opt/egov/app.jar 2>/dev/null; true
36+
RUN java -Xshare:dump \
37+
-XX:SharedClassListFile=/opt/egov/app.classlist \
38+
-XX:SharedArchiveFile=/opt/egov/app-cds.jsa \
39+
-jar /opt/egov/app.jar 2>/dev/null; true
40+
41+
# Ensure the start script has correct line endings and is executable
42+
RUN dos2unix /opt/egov/start.sh && chmod +x /opt/egov/start.sh
43+
44+
CMD ["/opt/egov/start.sh"]

build/maven-jdk21/start.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/sh
2+
3+
# JDK 21 auto-sizes heap from cgroup limits — no default -Xms/-Xmx needed.
4+
# Set JAVA_OPTS or JAVA_TOOL_OPTIONS via container environment if tuning is required.
5+
6+
# CDS: use shared archive if it exists (pre-baked at image build time)
7+
CDS_OPTS=""
8+
if [ -f /opt/egov/app-cds.jsa ]; then
9+
CDS_OPTS="-XX:SharedArchiveFile=/opt/egov/app-cds.jsa"
10+
fi
11+
12+
if [ x"${JAVA_ENABLE_DEBUG}" != x ] && [ "${JAVA_ENABLE_DEBUG}" != "false" ]; then
13+
java_debug_args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${JAVA_DEBUG_PORT:-5005}"
14+
fi
15+
16+
exec java ${java_debug_args} ${JAVA_OPTS} ${CDS_OPTS} ${JAVA_ARGS} -jar /opt/egov/app.jar

0 commit comments

Comments
 (0)