Multi-stage builds for Java

Docker · lesson 7 of 31 · 4 min read

Build the jar and run it from one Dockerfile while shipping only the runtime into the image.

Open this lesson in the learning hub

Key points

  • One Dockerfile, several FROM lines. Each FROM starts a fresh stage with an empty filesystem.
  • COPY --from=build pulls across only the artefact. Maven, the JDK and the local repo stay behind.
  • Typical result: a 700 MB build stage collapses into a runtime image around 250 MB.
  • No local Maven or JDK needed. The build runs inside Docker, so CI and laptops finally agree.
  • Name your stages with AS build, then --target build lets you stop early and inspect the build stage.

Example

# ---------- stage 1: build ----------
FROM maven:3.9-eclipse-temurin-21 AS build
WORKDIR /src

# dependencies first: this layer survives until pom.xml changes
COPY pom.xml .
RUN mvn -B -q dependency:go-offline

COPY src ./src
RUN mvn -B -q clean package -DskipTests

# ---------- stage 2: run ----------
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=build /src/target/*.jar app.jar

USER 10001
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

Build fat, ship thin. Multi-stage is the biggest single win for Java images.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Docker course, and every lesson in it is listed on the Docker contents page.