Skip to main content

Docker Image Optimization for Spring Boot

Docker images for Spring Boot applications often start bloated—large downloads, slow CI/CD pipelines, and unnecessary attack surface. This guide shows you how to dramatically reduce image size while improving security and build speed.

Overview

This guide covers three key optimization techniques:

  1. JRE Base Images - Using lightweight Alpine-based JRE images instead of full JDK distributions
  2. Multi-Stage Builds - Separating build and runtime environments for clean, consistent images
  3. Layered JARs - Breaking the Fat JAR into layers for blazing fast rebuilds and caching

Why Optimize?

ProblemImpact
Large image sizeSlow deployments, expensive registry storage
Full JDK in productionUnnecessary attack surface, security risk
Fat JAR changesEntire image re-uploaded on every code change
Inconsistent build environments"It works on my machine" issues

Summary of Improvements

TechniqueImage Size ImpactBuild Speed ImpactBenefit
JRE Base ImageHigh reductionMinimalSmaller footprint, better security
Multi-Stage BuildMedium reductionSlower first buildClean images, environment parity
Layered JARsMinimal size changeHuge increaseLightning-fast deployments and caching

Quick Start

Here's the complete optimized Dockerfile combining all three techniques:

# Stage 1: Extract layers from the JAR
FROM eclipse-temurin:17-jre-alpine as builder
WORKDIR /app
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract

# Stage 2: Create the runtime image
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]

Prerequisites

  • Spring Boot 2.3+ (for layered JAR support)
  • Docker 17.05+ (for multi-stage builds)
  • Maven or Gradle for building

Next Steps

Dive into each section to understand the concepts in detail:

Alternative: GraalVM Native Images

For even smaller images and near-instant startup, consider GraalVM Native Images. This compiles your Spring Boot application ahead-of-time into a native executable, eliminating the JVM entirely. Trade-offs include significantly longer build times and some limitations with dynamic Java features.