Docker cookbook · Intermediate

Build a layered image for a Spring Boot app

Package a Java service so dependency layers are cached and only your classes change on rebuild.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Build the jar in a JDK stage, extract Spring Boot's layers (dependencies, loader, snapshot dependencies, application) and copy them separately into a JRE runtime image, so dependency layers are reused across builds.

Solution

FROM eclipse-temurin:25-jdk AS build
WORKDIR /src
COPY . .
RUN ./mvnw -q -DskipTests package && \
    java -Djarmode=tools -jar target/app.jar extract --layers --launcher --destination /extracted

FROM eclipse-temurin:25-jre
WORKDIR /app
RUN useradd --uid 10001 --no-create-home app
COPY --from=build /extracted/dependencies/ ./
COPY --from=build /extracted/spring-boot-loader/ ./
COPY --from=build /extracted/snapshot-dependencies/ ./
COPY --from=build /extracted/application/ ./
USER 10001
ENV JAVA_TOOL_OPTIONS="-XX:MaxRAMPercentage=75"
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]

Pitfalls

  • One fat-jar layer: every code change re-uploads all dependencies.
  • Heap settings ignoring the container memory limit; use MaxRAMPercentage.
  • Running Maven without a dependency cache in CI, making builds slow.

Variations

  • Cloud Native Buildpacks (mvn spring-boot:build-image) produce layered images without a Dockerfile.
  • A jlink custom runtime for smaller images.

Further reading: Spring Boot: Dockerfiles

Reference: https://docs.spring.io/spring-boot/reference/packaging/container-images/dockerfiles.html

More Docker recipes

Was this page helpful?