diff --git a/build/build-config.yml b/build/build-config.yml index 8201faf8b7e..5c06a75f0b4 100644 --- a/build/build-config.yml +++ b/build/build-config.yml @@ -89,13 +89,13 @@ config: build: - work-dir: "core-services/egov-accesscontrol" image-name: "egov-accesscontrol" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" # Core Services - name: "builds/Digit-Core/core-services/audit-service" build: - work-dir: "core-services/audit-service" image-name: "audit-service" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/audit-service/src/main/resources/db" image-name: "audit-service-db" - name: "builds/Digit-Core/core-services/egov-common-masters" @@ -118,7 +118,7 @@ config: build: - work-dir: "core-services/egov-enc-service" image-name: "egov-enc-service" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-enc-service/src/main/resources/db" image-name: "egov-enc-service-db" @@ -126,7 +126,7 @@ config: build: - work-dir: "core-services/egov-filestore" image-name: "egov-filestore" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-filestore/src/main/resources/db" image-name: "egov-filestore-db" @@ -134,7 +134,7 @@ config: build: - work-dir: "core-services/egov-idgen" image-name: "egov-idgen" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-idgen/src/main/resources/db" image-name: "egov-idgen-db" @@ -142,7 +142,7 @@ config: build: - work-dir: "core-services/egov-indexer" image-name: "egov-indexer" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-indexer/src/main/resources/db" image-name: "egov-indexer-db" @@ -150,7 +150,7 @@ config: build: - work-dir: "core-services/egov-localization" image-name: "egov-localization" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-localization/src/main/resources/db" image-name: "egov-localization-db" @@ -158,7 +158,7 @@ config: build: - work-dir: "core-services/egov-location" image-name: "egov-location" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-location/src/main/resources/db" image-name: "egov-location-db" @@ -166,7 +166,7 @@ config: build: - work-dir: "core-services/boundary-service" image-name: "boundary-service" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/boundary-service/src/main/resources/db" image-name: "boundary-service-db" @@ -174,13 +174,13 @@ config: build: - work-dir: "core-services/egov-mdms-service" image-name: "egov-mdms-service" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - name: "builds/Digit-Core/core-services/mdms-v2" build: - work-dir: "core-services/mdms-v2" image-name: "mdms-v2" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/mdms-v2/src/main/resources/db" image-name: "mdms-v2-db" @@ -188,19 +188,19 @@ config: build: - work-dir: "core-services/egov-notification-mail" image-name: "egov-notification-mail" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - name: "builds/Digit-Core/core-services/egov-notification-sms" build: - work-dir: "core-services/egov-notification-sms" image-name: "egov-notification-sms" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - name: "builds/Digit-Core/core-services/egov-otp" build: - work-dir: "core-services/egov-otp" image-name: "egov-otp" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-otp/src/main/resources/db" image-name: "egov-otp-db" @@ -208,13 +208,13 @@ config: build: - work-dir: "core-services/egov-persister" image-name: "egov-persister" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - name: "builds/Digit-Core/core-services/egov-pg-service" build: - work-dir: "core-services/egov-pg-service" image-name: "egov-pg-service" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-pg-service/src/main/resources/db" image-name: "egov-pg-service-db" @@ -234,7 +234,7 @@ config: build: - work-dir: "core-services/egov-user" image-name: "egov-user" - dockerfile: "build/maven-java8/Dockerfile" + dockerfile: "build/maven-java8-jdk21/Dockerfile" - work-dir: "core-services/egov-user/src/main/resources/db" image-name: "egov-user-db" @@ -242,7 +242,7 @@ config: build: - work-dir: "core-services/egov-user-event" image-name: "egov-user-event" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-user-event/src/main/resources/db" image-name: "egov-user-event-db" @@ -250,7 +250,7 @@ config: build: - work-dir: "core-services/egov-workflow-v2" image-name: "egov-workflow-v2" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-workflow-v2/src/main/resources/db" image-name: "egov-workflow-v2-db" @@ -303,7 +303,7 @@ config: build: - work-dir: "core-services/user-otp" image-name: "user-otp" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - name: "builds/Digit-Core/core-services/zuul" build: @@ -315,7 +315,7 @@ config: build: - work-dir: "core-services/gateway" image-name: "gateway" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - name: "builds/Digit-Core/core-services/internal-gateway" build: @@ -327,15 +327,15 @@ config: build: - work-dir: "core-services/internal-gateway-scg" image-name: "internal-gateway-scg" - dockerfile: "build/maven/Dockerfile" - + dockerfile: "build/maven-jdk21/Dockerfile" + - name: "builds/Digit-Core/core-services/egov-user-event" build: - work-dir: "core-services/egov-user-event" image-name: "egov-user-event" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-user-event/src/main/resources/db" - image-name: "egov-user-event-db" + image-name: "egov-user-event-db" - name: "builds/Digit-Core/core-services/pdf-service" build: @@ -360,7 +360,7 @@ config: build: - work-dir: "core-services/egov-url-shortening" image-name: "egov-url-shortening" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/egov-url-shortening/src/main/resources/db" image-name: "egov-url-shortening-db" @@ -444,7 +444,7 @@ config: build: - work-dir: "accelerators/inbox" image-name: "inbox" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - name: "builds/Digit-Core/accelerators/gateway-kubernetes-discovery" build: @@ -455,7 +455,7 @@ config: build: - work-dir: "accelerators/pgr-services" image-name: "pgr-services" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "accelerators/pgr-services/src/main/resources/db" image-name: "pgr-services-db" @@ -463,7 +463,7 @@ config: build: - work-dir: "core-services/service-request" image-name: "service-request" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven-jdk21/Dockerfile" - work-dir: "core-services/service-request/src/main/resources/db" image-name: "service-request-db" diff --git a/build/maven-java8-jdk21/Dockerfile b/build/maven-java8-jdk21/Dockerfile new file mode 100644 index 00000000000..36b7cd8ddc3 --- /dev/null +++ b/build/maven-java8-jdk21/Dockerfile @@ -0,0 +1,78 @@ +# JDK 8→21 hybrid: compile with JDK 8, run on JDK 21. +# Use this for services on Spring Boot 1.5/2.x that cannot be recompiled +# for JDK 17+ but benefit from JDK 21's cgroup v2 fix and memory improvements. +# +# JDK 21 fixes cgroup v2 CPU detection (JDK-8281181), auto-sizes heap/threads +# from container limits, and runs Java 8 bytecode natively. +# +# Spring Boot 1.5 needs two runtime patches for JDK 21: +# 1. JAXB API + runtime (removed from JDK 11) +# 2. --add-opens flags for internal JDK module access + +# ──────────────── BUILD STAGE ──────────────── +FROM egovio/maven:3.9.6-amazoncorretto-8-debian AS build +ARG WORK_DIR +WORKDIR /app + +COPY ${WORK_DIR}/pom.xml ./pom.xml +COPY build/maven-java8-jdk21/start.sh ./start.sh +COPY ${WORK_DIR}/src ./src + +RUN mvn -B -f pom.xml package -DskipTests + +# ──────────── JAXB PATCH STAGE ───────────── +FROM eclipse-temurin:21-jdk-alpine AS patcher +RUN apk add --no-cache curl +WORKDIR /patch + +COPY --from=build /app/target/*.jar ./app.jar + +# Download JAXB API + implementation (removed from JDK 11+) +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 && \ + 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 && \ + 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 && \ + curl -sL -o txw2.jar https://repo1.maven.org/maven2/org/glassfish/jaxb/txw2/2.3.9/txw2-2.3.9.jar && \ + 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 && \ + 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 + +# Inject JAXB jars into the fat JAR (jar uf0 preserves STORED entries) +RUN mkdir -p BOOT-INF/lib && \ + cp jaxb-api.jar javax.activation.jar jaxb-runtime.jar txw2.jar \ + istack-commons-runtime.jar stax-ex.jar BOOT-INF/lib/ && \ + jar uf0 app.jar \ + BOOT-INF/lib/jaxb-api.jar \ + BOOT-INF/lib/javax.activation.jar \ + BOOT-INF/lib/jaxb-runtime.jar \ + BOOT-INF/lib/txw2.jar \ + BOOT-INF/lib/istack-commons-runtime.jar \ + BOOT-INF/lib/stax-ex.jar + +# ─────────────── RUNTIME STAGE ─────────────── +FROM eclipse-temurin:21-jre-alpine + +RUN apk add --no-cache dos2unix + +WORKDIR /opt/egov + +COPY --from=patcher /patch/app.jar /opt/egov/app.jar +COPY --from=build /app/start.sh /opt/egov/start.sh + +# CDS pre-dump: generate classlist then shared archive for faster startup. +RUN timeout 30 java \ + --add-opens java.base/java.lang=ALL-UNNAMED \ + --add-opens java.base/java.lang.reflect=ALL-UNNAMED \ + --add-opens java.base/java.util=ALL-UNNAMED \ + -XX:DumpLoadedClassList=/opt/egov/app.classlist \ + -jar /opt/egov/app.jar 2>/dev/null; true +RUN java \ + --add-opens java.base/java.lang=ALL-UNNAMED \ + --add-opens java.base/java.lang.reflect=ALL-UNNAMED \ + --add-opens java.base/java.util=ALL-UNNAMED \ + -Xshare:dump \ + -XX:SharedClassListFile=/opt/egov/app.classlist \ + -XX:SharedArchiveFile=/opt/egov/app-cds.jsa \ + -jar /opt/egov/app.jar 2>/dev/null; true + +RUN dos2unix /opt/egov/start.sh && chmod +x /opt/egov/start.sh + +CMD ["/opt/egov/start.sh"] diff --git a/build/maven-java8-jdk21/start.sh b/build/maven-java8-jdk21/start.sh new file mode 100644 index 00000000000..112e447e632 --- /dev/null +++ b/build/maven-java8-jdk21/start.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# JDK 21 auto-sizes heap from cgroup limits — no default -Xms/-Xmx needed. +# Set JAVA_OPTS or JAVA_TOOL_OPTIONS via container environment if tuning is required. + +# CDS: use shared archive if it exists (pre-baked at image build time) +CDS_OPTS="" +if [ -f /opt/egov/app-cds.jsa ]; then + CDS_OPTS="-XX:SharedArchiveFile=/opt/egov/app-cds.jsa" +fi + +# Spring Boot 1.5 uses internal JDK APIs via reflection. +# These --add-opens flags are required for JDK 21 compatibility. +ADD_OPENS="--add-opens java.base/java.lang=ALL-UNNAMED" +ADD_OPENS="$ADD_OPENS --add-opens java.base/java.lang.reflect=ALL-UNNAMED" +ADD_OPENS="$ADD_OPENS --add-opens java.base/java.util=ALL-UNNAMED" + +if [ x"${JAVA_ENABLE_DEBUG}" != x ] && [ "${JAVA_ENABLE_DEBUG}" != "false" ]; then + java_debug_args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${JAVA_DEBUG_PORT:-5005}" +fi + +exec java ${java_debug_args} ${ADD_OPENS} ${JAVA_OPTS} ${CDS_OPTS} ${JAVA_ARGS} -jar /opt/egov/app.jar diff --git a/build/maven-jdk21/Dockerfile b/build/maven-jdk21/Dockerfile new file mode 100644 index 00000000000..699f0f06e20 --- /dev/null +++ b/build/maven-jdk21/Dockerfile @@ -0,0 +1,44 @@ +# JDK 21 runtime variant of build/maven/Dockerfile. +# Use this for services on Spring Boot 3.x compiled with Java 17+. +# Services on Spring Boot 1.5/2.x must continue using build/maven/Dockerfile. +# +# JDK 21 fixes cgroup v2 CPU detection (JDK-8281181), auto-sizes heap/threads +# from container limits, and runs Java 17 bytecode natively (no recompilation). + +FROM egovio/maven:3.9.6-amazoncorretto-17 AS build +ARG WORK_DIR +WORKDIR /app + +# Copy project files +COPY ${WORK_DIR}/pom.xml ./pom.xml +COPY build/maven-jdk21/start.sh ./start.sh +COPY ${WORK_DIR}/src ./src + +# Build the project +RUN mvn -B -f /app/pom.xml package + +# Runtime image — JDK 21 on Alpine +FROM eclipse-temurin:21-jre-alpine + +RUN apk add --no-cache dos2unix + +WORKDIR /opt/egov + +# Copy artifacts from the build stage +COPY --from=build /app/target/*.jar /opt/egov/app.jar +COPY --from=build /app/start.sh /opt/egov/start.sh + +# CDS pre-dump: generate classlist then shared archive for faster startup. +# The app will attempt to start (no DB/Kafka available) — timeout kills it +# after 30s, which is enough to load all classes for the classlist. +RUN timeout 30 java -XX:DumpLoadedClassList=/opt/egov/app.classlist \ + -jar /opt/egov/app.jar 2>/dev/null; true +RUN java -Xshare:dump \ + -XX:SharedClassListFile=/opt/egov/app.classlist \ + -XX:SharedArchiveFile=/opt/egov/app-cds.jsa \ + -jar /opt/egov/app.jar 2>/dev/null; true + +# Ensure the start script has correct line endings and is executable +RUN dos2unix /opt/egov/start.sh && chmod +x /opt/egov/start.sh + +CMD ["/opt/egov/start.sh"] diff --git a/build/maven-jdk21/start.sh b/build/maven-jdk21/start.sh new file mode 100644 index 00000000000..d8fcc20d31a --- /dev/null +++ b/build/maven-jdk21/start.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# JDK 21 auto-sizes heap from cgroup limits — no default -Xms/-Xmx needed. +# Set JAVA_OPTS or JAVA_TOOL_OPTIONS via container environment if tuning is required. + +# CDS: use shared archive if it exists (pre-baked at image build time) +CDS_OPTS="" +if [ -f /opt/egov/app-cds.jsa ]; then + CDS_OPTS="-XX:SharedArchiveFile=/opt/egov/app-cds.jsa" +fi + +if [ x"${JAVA_ENABLE_DEBUG}" != x ] && [ "${JAVA_ENABLE_DEBUG}" != "false" ]; then + java_debug_args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${JAVA_DEBUG_PORT:-5005}" +fi + +exec java ${java_debug_args} ${JAVA_OPTS} ${CDS_OPTS} ${JAVA_ARGS} -jar /opt/egov/app.jar diff --git a/build/maven/Dockerfile b/build/maven/Dockerfile index b68795aed18..bc8f4cc7b3f 100644 --- a/build/maven/Dockerfile +++ b/build/maven/Dockerfile @@ -10,18 +10,29 @@ COPY ${WORK_DIR}/src ./src # Build the project RUN mvn -B -f /app/pom.xml package -# Runtime image – using a multi-arch base image -FROM egovio/amazoncorretto:17-alpine +# Runtime image – JDK 21 fixes cgroup v2 CPU detection (JDK-8281181), +# auto-sizes heap/threads from container limits, and runs Java 17 bytecode natively. +FROM eclipse-temurin:21-jre-alpine + +RUN apk add --no-cache dos2unix WORKDIR /opt/egov # Copy artifacts from the build stage -COPY --from=build /app/target/*.jar /app/start.sh /opt/egov/ +COPY --from=build /app/target/*.jar /opt/egov/app.jar +COPY --from=build /app/start.sh /opt/egov/start.sh + +# CDS pre-dump: generate classlist then shared archive for faster startup. +# The app will attempt to start (no DB/Kafka available) — timeout kills it +# after 30s, which is enough to load all classes for the classlist. +RUN timeout 30 java -XX:DumpLoadedClassList=/opt/egov/app.classlist \ + -jar /opt/egov/app.jar 2>/dev/null; true +RUN java -Xshare:dump \ + -XX:SharedClassListFile=/opt/egov/app.classlist \ + -XX:SharedArchiveFile=/opt/egov/app-cds.jsa \ + -jar /opt/egov/app.jar 2>/dev/null; true # Ensure the start script has correct line endings and is executable RUN dos2unix /opt/egov/start.sh && chmod +x /opt/egov/start.sh -# Verify architecture inside the container -RUN uname -m - CMD ["/opt/egov/start.sh"] \ No newline at end of file diff --git a/build/maven/start.sh b/build/maven/start.sh index 08bdd8de28e..d8fcc20d31a 100644 --- a/build/maven/start.sh +++ b/build/maven/start.sh @@ -1,11 +1,16 @@ #!/bin/sh -if [[ -z "${JAVA_OPTS}" ]];then - export JAVA_OPTS="-Xmx64m -Xms64m" +# JDK 21 auto-sizes heap from cgroup limits — no default -Xms/-Xmx needed. +# Set JAVA_OPTS or JAVA_TOOL_OPTIONS via container environment if tuning is required. + +# CDS: use shared archive if it exists (pre-baked at image build time) +CDS_OPTS="" +if [ -f /opt/egov/app-cds.jsa ]; then + CDS_OPTS="-XX:SharedArchiveFile=/opt/egov/app-cds.jsa" fi if [ x"${JAVA_ENABLE_DEBUG}" != x ] && [ "${JAVA_ENABLE_DEBUG}" != "false" ]; then java_debug_args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${JAVA_DEBUG_PORT:-5005}" fi -exec java ${java_debug_args} ${JAVA_OPTS} ${JAVA_ARGS} -jar /opt/egov/*.jar \ No newline at end of file +exec java ${java_debug_args} ${JAVA_OPTS} ${CDS_OPTS} ${JAVA_ARGS} -jar /opt/egov/app.jar