Gymterview
middle

Что такое multi-stage build и зачем он нужен?

Multi-stage build (многоступенчатая сборка) — это подход, при котором в одном Dockerfile используется несколько инструкций FROM, где каждая начинает новую стадию сборки, а в финальный образ попадает только результат последней стадии.

Зачем нужен

  • Разделение среды сборки и среды выполнения
  • Уменьшение размера финального образа — в него не попадают инструменты сборки (Maven, Gradle, JDK)
  • Один Dockerfile для всего процесса — от исходного кода до готового образа

Пример для Spring Boot приложения с Maven

Пример
# --- Стадия 1: сборка ---
FROM maven:3.9-eclipse-temurin-17 AS build
WORKDIR /app
COPY pom.xml .
# Загружаем зависимости отдельным слоем (кэширование)
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn package -DskipTests -B

# --- Стадия 2: запуск ---
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
# Копируем только JAR из стадии сборки
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Результат: финальный образ содержит только JRE и JAR-файл, без Maven, JDK, исходного кода и промежуточных артефактов. Размер образа может уменьшиться с ~800 МБ до ~200 МБ.

Пример с Gradle
FROM gradle:8.5-jdk17 AS build
WORKDIR /app
COPY build.gradle settings.gradle ./
COPY src ./src
RUN gradle bootJar --no-daemon

FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=build /app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

На собеседовании: объясните главную идею: multi-stage build позволяет собирать приложение в одном контейнере (с JDK и Maven), а запускать в другом (только JRE). Это уменьшает размер образа и поверхность атаки. Покажите, что знаете синтаксис COPY --from=build.