Bird
Raised Fist0
Spring Bootframework~10 mins

Multi-stage Docker builds in Spring Boot - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Multi-stage Docker builds
Start: Base Build Stage
↓
Compile & Package App
↓
Create Smaller Runtime Stage
↓
Copy Artifacts from Build Stage
↓
Set Runtime Environment
↓
Build Final Image
↓
Run Container with Final Image
The Dockerfile first builds the app in one stage, then copies only the needed files to a smaller image for running.
Execution Sample
Spring Boot
FROM maven:3.8.7-openjdk-17 AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests

FROM openjdk:17-jdk-slim
COPY --from=build /app/target/*.jar /app/app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
This Dockerfile builds a Spring Boot app with Maven, then creates a smaller image with just the jar to run.
Execution Table
StepActionStageFiles PresentResult
1Start build stage with Maven imagebuildBase image ready
2Copy pom.xmlbuildpom.xmlpom.xml copied
3Copy src directorybuildpom.xml, src/Source code copied
4Run mvn clean packagebuildpom.xml, src/, target/app.jarJar file created
5Start runtime stage with OpenJDK slimruntimeClean runtime image
6Copy jar from build stageruntimeapp.jarJar copied to runtime
7Set ENTRYPOINT to run jarruntimeapp.jarRuntime ready to start app
8Build final imagefinalapp.jarFinal image built with only runtime files
9Run container from final imagefinalapp.jarApp runs with minimal image
💡 All build steps complete; final image contains only runtime essentials.
Variable Tracker
VariableStartAfter Step 4After Step 6Final
pom.xmlabsentpresentabsentabsent
src/absentpresentabsentabsent
target/app.jarabsentpresentabsentabsent
app.jar in runtimeabsentabsentpresentpresent
Key Moments - 3 Insights
Why is the source code not present in the final image?
Because the source code is copied only in the build stage (see step 3) and not copied to the runtime stage (step 6 copies only the jar). This keeps the final image small.
How does the final image get the jar file without rebuilding?
The final image copies the jar from the build stage using the --from=build syntax (step 6), so it reuses the built artifact without recompiling.
Why use two different base images?
The build stage uses a Maven image with tools to compile the app, while the runtime stage uses a smaller OpenJDK image to run the app efficiently (steps 1 and 5).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, at which step is the jar file created?
AStep 2
BStep 6
CStep 4
DStep 8
💡 Hint
Check the 'Result' column for when 'Jar file created' appears.
At which step does the runtime stage start?
AStep 1
BStep 5
CStep 7
DStep 9
💡 Hint
Look for the step mentioning 'Start runtime stage with OpenJDK slim'.
If we copied the src folder to the runtime stage, what would happen?
AThe final image size would increase
BThe jar file would be rebuilt automatically
CThe app would run faster
DThe build stage would fail
💡 Hint
Refer to variable_tracker showing src/ presence only in build stage.
Concept Snapshot
Multi-stage Docker builds use multiple FROM lines.
First stage builds the app with all tools.
Second stage copies only needed files (like jar).
Final image is smaller and cleaner.
Use --from=stage to copy artifacts.
Improves build efficiency and image size.
Full Transcript
Multi-stage Docker builds start by using a base image with build tools to compile the Spring Boot app. The source code and pom.xml are copied into this build stage. Then the app is compiled with Maven, producing a jar file. Next, a second stage uses a smaller runtime image. It copies only the jar file from the build stage. This keeps the final image small and efficient. The ENTRYPOINT is set to run the jar. The container runs the app with minimal files. This process separates building and running, improving speed and size.

Practice

(1/5)
1. What is the main benefit of using multi-stage Docker builds for a Spring Boot application?
easy
A. It creates smaller and cleaner Docker images by separating build and runtime stages.
B. It allows running multiple containers from the same image simultaneously.
C. It automatically updates the Spring Boot version inside the container.
D. It enables running the application without a Dockerfile.

Solution

  1. Step 1: Understand multi-stage build purpose

    Multi-stage builds separate the build environment from the runtime environment to reduce image size.
  2. Step 2: Identify benefit for Spring Boot apps

    By copying only the needed files from build to runtime stage, the final image is smaller and cleaner.
  3. Final Answer:

    It creates smaller and cleaner Docker images by separating build and runtime stages. -> Option A
  4. Quick Check:

    Multi-stage builds = smaller images [OK]
Hint: Multi-stage builds reduce image size by splitting build and run [OK]
Common Mistakes:
  • Confusing multi-stage builds with running multiple containers
  • Thinking it updates Spring Boot version automatically
  • Believing Dockerfile is not needed
2. Which of the following is the correct syntax to start a new build stage named 'builder' in a Dockerfile?
easy
A. NEW STAGE builder FROM openjdk:17
B. FROM openjdk:17 AS builder
C. BUILD openjdk:17 AS builder
D. STAGE builder FROM openjdk:17

Solution

  1. Step 1: Recall Dockerfile multi-stage syntax

    The correct syntax to start a build stage is 'FROM <image> AS <name>'.
  2. Step 2: Match syntax to options

    Only FROM openjdk:17 AS builder uses 'FROM openjdk:17 AS builder' which is valid.
  3. Final Answer:

    FROM openjdk:17 AS builder -> Option B
  4. Quick Check:

    Multi-stage start = FROM ... AS ... [OK]
Hint: Use 'FROM image AS name' to start a build stage [OK]
Common Mistakes:
  • Using 'STAGE' or 'BUILD' keywords incorrectly
  • Placing 'AS' after the stage name
  • Writing 'NEW STAGE' which is invalid
3. Given this Dockerfile snippet for a Spring Boot app:
FROM maven:3.8.6-openjdk-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests

FROM openjdk:17-jdk-slim
COPY --from=builder /app/target/myapp.jar /app/myapp.jar
ENTRYPOINT ["java", "-jar", "/app/myapp.jar"]
What will be the size impact of this multi-stage build compared to a single-stage build including Maven?
medium
A. The final image will be smaller because Maven and source files are excluded.
B. The final image will be larger because it contains both Maven and JDK.
C. The final image size is the same as a single-stage build.
D. The final image will fail to build due to missing source files.

Solution

  1. Step 1: Analyze multi-stage build steps

    The first stage builds the app with Maven, the second stage copies only the jar file.
  2. Step 2: Understand image size impact

    Since Maven and source code are not copied to the final image, it is smaller than a single-stage build including Maven.
  3. Final Answer:

    The final image will be smaller because Maven and source files are excluded. -> Option A
  4. Quick Check:

    Copy only jar = smaller image [OK]
Hint: Final image excludes build tools, so it's smaller [OK]
Common Mistakes:
  • Assuming Maven stays in final image
  • Thinking source files are copied to final image
  • Believing multi-stage builds cause build failure here
4. Identify the error in this Dockerfile snippet for a multi-stage build:
FROM openjdk:17 AS builder
WORKDIR /app
COPY . .
RUN ./mvnw package

FROM openjdk:17-jdk-slim
COPY /app/target/app.jar /app/app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
medium
A. The first stage should use a Maven image, not openjdk.
B. The ENTRYPOINT syntax is incorrect and will cause a runtime error.
C. The WORKDIR command is missing in the second stage.
D. The COPY command in the second stage uses an absolute path instead of a relative path from the builder stage.

Solution

  1. Step 1: Check COPY command in second stage

    The COPY command uses '/app/target/app.jar' which is an absolute path on the host, not from the builder stage.
  2. Step 2: Correct COPY syntax for multi-stage

    It should be 'COPY --from=builder /app/target/app.jar /app/app.jar' to copy from the builder stage.
  3. Final Answer:

    The COPY command in the second stage uses an absolute path instead of a relative path from the builder stage. -> Option D
  4. Quick Check:

    Use COPY --from=builder for multi-stage files [OK]
Hint: Use COPY --from=stage to copy files between stages [OK]
Common Mistakes:
  • Forgetting --from=builder in COPY
  • Assuming ENTRYPOINT syntax is wrong
  • Thinking WORKDIR is required in second stage
5. You want to optimize a Spring Boot Dockerfile using multi-stage builds. Which approach best reduces the final image size while ensuring the app runs correctly?
hard
A. Build the app and run it in the same stage using a full Maven and JDK image.
B. Copy the entire source code and Maven cache to the final image for faster startup.
C. Use a Maven build stage to compile, then copy only the fat jar to a minimal JRE base image in the final stage.
D. Use multiple runtime stages with different JDK versions to support various environments.

Solution

  1. Step 1: Understand multi-stage build optimization

    Building with Maven in one stage and copying only the final jar to a minimal runtime image reduces size.
  2. Step 2: Evaluate options for best practice

    Use a Maven build stage to compile, then copy only the fat jar to a minimal JRE base image in the final stage. uses a build stage with Maven and a minimal JRE image for runtime, which is optimal.
  3. Final Answer:

    Use a Maven build stage to compile, then copy only the fat jar to a minimal JRE base image in the final stage. -> Option C
  4. Quick Check:

    Build then minimal runtime = smallest image [OK]
Hint: Build with Maven, run with minimal JRE for smallest image [OK]
Common Mistakes:
  • Running build and runtime in one large image
  • Copying unnecessary source code to final image
  • Using multiple runtime stages unnecessarily
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard