✦ For everyone, free.

Practical knowledge for real and everyday life

Home

12.2.1.3 Java JAR Packaging

A focused guide to Java JAR Packaging, connecting core concepts with practical Docker and container operations.

Java JAR packaging produces the final, executable artifact a Java application's runtime stage actually runs, typically a single, self-contained "fat" or "uber" JAR bundling the application's compiled code along with all of its dependencies into one file.

Building a Self-Contained JAR

Most Java build tools, with appropriate plugin configuration, can produce a single JAR containing both the application's code and its dependencies.

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
mvn package

This produces a single, executable JAR with every dependency bundled inside it, ready to run with nothing more than a JVM.

Running the Packaged JAR in the Final Runtime Stage

The final stage of a multi-stage Dockerfile simply copies this self-contained JAR and runs it directly.

FROM eclipse-temurin:21-jre-alpine
COPY --from=build /app/target/myapp.jar /app/myapp.jar
CMD ["java", "-jar", "/app/myapp.jar"]
Why a Self-Contained JAR Simplifies the Runtime Image

Since every dependency is already bundled within the single JAR file, the runtime stage needs nothing beyond the JRE itself and this one artifact, keeping the final image both simple and minimal.

docker run --rm myapp:1.0

This runs correctly without needing any separate dependency installation step in the runtime image at all.

Considering Layered JARs for More Efficient Image Updates

Some frameworks support producing a "layered" JAR, splitting dependencies from application code into separate layers, allowing Docker's own layer caching to avoid re-transferring unchanged dependency layers when only application code changes.

RUN java -Djarmode=layertools -jar myapp.jar extract
COPY --from=build /app/dependencies/ ./
COPY --from=build /app/application/ ./
Why Java JAR Packaging Matters

Producing a properly packaged, self-contained JAR is the key artifact connecting a Java application's build stage to its final, minimal runtime stage, and understanding packaging options like layered JARs can further improve build and deployment efficiency.