본문 바로가기
배포·CI,CD·클라우드

Dockerfile 멀티스테이지로 이미지 절반 만들기

by yamoojin83 2025. 10. 4.

Dockerfile 멀티스테이지로 이미지 절반 만들기

멀티스테이지 빌드는 “빌드에 필요한 도구(JDK·Gradle)는 첫 단계에서만 사용하고, 런타임 단계에는 결과물만 담는” 방식입니다. 이를 적용하면 이미지 용량을 절반 이하로 줄이고, 보안 표면을 크게 줄일 수 있습니다.

프로젝트 준비(.dockerignore)


# .dockerignore
.git
.gradle
build
out
**/.DS_Store

예시: Spring Boot 3 + Gradle + JDK 21


# syntax=docker/dockerfile:1.7

########## 1) Builder Stage ##########
FROM eclipse-temurin:21-jdk AS builder
WORKDIR /app

# Gradle 캐시 활성화 (BuildKit 필요)
# 의존성 캐시를 먼저 만들고, 그 후 소스를 복사하면 레이어 캐시 적중률이 높습니다.
COPY gradlew gradlew.bat settings.gradle.kts build.gradle.kts ./
COPY gradle gradle
RUN --mount=type=cache,target=/root/.gradle \
    ./gradlew --version

# 소스 복사 후 빌드
COPY src src
RUN --mount=type=cache,target=/root/.gradle \
    ./gradlew clean bootJar -x test

########## 2) Runtime Stage ##########
# 경량 & 보안: 리눅스 유저랜드 최소, 쉘·패키지 매니저 없음
FROM gcr.io/distroless/java21-debian12 AS runner
WORKDIR /app

# 비루트 사용자
USER nonroot:nonroot

# 앱 JAR 복사 (Spring Boot 3는 기본 Layered Jar 지원)
COPY --from=builder /app/build/libs/*.jar app.jar

# 헬스체크는 오케스트레이터가 대신 수행하는 것을 권장하나, 단독 실행 시 다음 예시 활용
# (distroless에는 쉘이 없으므로 curl 기반 체크는 별도 사이드카 등으로 처리)
# HEALTHCHECK NONE

EXPOSE 8080
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar"]

이미지 크기/보안 이점

  • Builder(약 600MB) → Runner(약 80~100MB). 최종 이미지엔 JRE만 포함.
  • 패키지 매니저/쉘 미포함 → 공격 표면 축소.

빌드/실행


DOCKER_BUILDKIT=1 docker build -t app:1.0 .
docker run -p 8080:8080 app:1.0

자주 하는 실수

  • 캐시 무효화: 소스 전체를 먼저 복사하면 의존성 캐시가 매번 깨집니다.
  • 루트 실행: USER nonroot 생략 시 컨테이너 권한 과도.
  • 레이어 폭증: 불필요한 RUN 분리. 논리적으로 묶어 최소화.

 

 

👉 1편: Dockerfile 멀티스테이지로 이미지 절반 만들기

👉 2편: GitHub Actions: push 시 테스트 자동화 YAML

👉 3편: Jackson 직·역직렬화 어노테이션 핵심(@Json*)

👉 4편: springdoc-openapi로 API 문서 1분 셋업