임대일

4.6 도커(Docker) 이미지 빌드: 멀티 스테이지 빌드(Multi-Stage-Build) 본문

도커/개발자를 위한 쉬운 도커

4.6 도커(Docker) 이미지 빌드: 멀티 스테이지 빌드(Multi-Stage-Build)

limdae94 2024. 6. 29. 18:50
 

개발자를 위한 쉬운 도커 강의 | 데브위키 - 인프런

데브위키 | 현업 개발자가 도커를 사용한 경험을 녹여낸 새로운 커리큘럼으로 기존 교재 및 강의와 차별된 강의를 제공합니다. 단순한 명령어 사용법이 아닌 도커를 왜 사용해야하는지 대한 근

www.inflearn.com

 

1. 멀티 스테이징 빌드

 

멀티 스테이징 빌드는 도커 파일에서 두 개의 베이스 이미지를 활용하는 방법이다. 보통 애플리케이션을 빌드하는 과정에서 만들어지는 파일들이 용량을 많이 차지한다. 생성된 파일들은 실제로 애플리케이션이 실행되는데 사용되지 않기 때문에 이미지를 빌드에 사용하는 이미지실행에 사용하는 이미지로 나누는 것이다. 멀티 스테이징 빌드를 잘 활용하면 실제로 애플리케이션이 실행되는 이미지의 크기를 줄일 수 있다.

 

Spring Boot 애플리케이션 이미지 구성

Spring Boot 프레임워크를 빌드해보자. 스프링 부트는 jar 혹은 war 으로 빌드가 가능하다. 보통 jar로 빌드를 수행하고 jar를 실행시키기 위해서 OS 안에 Java Runtime이 필요하다. 그리고 소스 코드를 실행하기 위해서는 Maven 혹은 Gradle이라는 자바 빌드 도구가 필요하다. 실습 예제에서는 메이븐으로 자바 소스 코드를 빌드한다. 위의 그림과 같은 순서로 실행 순서는 아래에서부터 위로 향하게 된다. 실행된 애플리케이션은 웹 페이지에서 확인할 수 있다.

 

Dockerfile.singlestage

# 빌드 환경 설정
FROM maven:3.6-jdk-11
WORKDIR /app

# pom.xml과 src/ 디렉토리 복사
COPY pom.xml .
COPY src ./src

# 애플리케이션 빌드
RUN mvn clean package

# 빌드된 JAR 파일을 실행 환경으로 복사
RUN cp /app/target/*.jar ./app.jar

# 애플리케이션 실행
EXPOSE 8080
CMD [ "java", "-jar", "app.jar" ]

자바 컨텍스트를 실행하는 자바 애플리케이션 이미지를 생성할 수 있다. 이때 애플리케이션 이미지에 불필요한 Maven 파일까지 포함되어 이미지의 크기가 커진다. 일반적으로 Maven 이미지와 애플리케이션 이미지를 분리해야 불필요한 이미지 크기를 줄여서 실행 속도를 높인다.

 

Multi-Staging Spring Boot 이미지 구

애플리케이션을 빌드할 때 필요한 정보는 Maven 도구와 소스 코드이다. 그리고 애플리케이션을 실행할 때는 자바 런타임과 Jar 파일만 있으면 된다. 따라서 첫 번째 단계에서는 소스 코드를 복사한 다음에 mvn clean package 명령을 사용해서 jar 파일을 생성한다. 그리고 실제로 애플리케이션을 실행하는 이미지에서는 Java Runtime만 있는 이미지를 가져오고, 빌드한 결과물에서 jar 파일을 복사해 와서 애플리케이션을 실행에 사용할 것이다.

이런 방법으로 이미지를 빌드할 때 애플리케이션 빌드에 사용하는 빌드 스테이지이미지를 실행하는 실행 스테이지 두 개로 나누어서 빌드하는 방식을 멀티 스테이지 빌드라고 부른다.

 

FROM AS

멀티 스테이지 빌드는 FROM 지시어가 두 개가 있다. 첫 번째는 빌드 스테이지에 필요한 Maven 빌드 환경 설정이고 이미지를 실행하는 실행 스테이지인 openjdk:11-jre-slim으로 Java Runtim이 존재한다. COPY 에는 다른 지시어와 다르게 --from=build 가 있다. 다른 스테이지에서 파일을 가져올 때 지정하는 방법이다. 이제 싱글 스테이지 빌드와 멀티 스테이지 빌드를 통해서 얼마나 파일 크기가 차이나는지 실습한다.

 

# 빌드 환경 설정
FROM maven:3.6-jdk-11
WORKDIR /app

# pom.xml과 src/ 디렉토리 복사
COPY pom.xml .
COPY src ./src

# 애플리케이션 빌드
RUN mvn clean package

# 빌드된 JAR 파일을 실행 환경으로 복사
RUN cp /app/target/*.jar ./app.jar

# 애플리케이션 실행
EXPOSE 8080
CMD [ "java", "-jar", "app.jar" ]

docker build -f Dockerfile.singlestage -t javaappsingle .

docker build -f Dockerfile.singlestage -t javaappsingle . 
# 빌드 환경 설정
FROM maven:3.6 AS build
WORKDIR /app

# pom.xml과 src/ 디렉토리 복사
COPY pom.xml .
COPY src ./src

# 애플리케이션 빌드
RUN mvn clean package

# 두번째 단계: 실행 환경 설정
FROM openjdk:11-jre-slim
WORKDIR /app

# 빌드 단계에서 생성된 JAR 파일 복사
COPY --from=build /app/target/*.jar ./app.jar

# 애플리케이션 실행
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]

docker build -f Dockerfile.multistage -t javaappmulti .

docker build -f Dockerfile.multisatge -t javaappmulti .

 

docker image ls javaappsingle
docker image ls javaappmulti

싱글 스테이지와 멀티 스테이지 도커 파일을 모두 빌드하고 이미지 크기를 살펴보면, 3배 가까이 이미지 크기가 다르다는 것을 확인할 수 있다. 이처럼 스프링 부트 환경에서 도커 파일을 멀티 스테이지 방식으로 작성해야 불필요한 파일을 제외하고 빌드를 수행한다.

 

Dockerfile.singlestage 빌드 구성

위의 그림은 싱글 스테이지 빌드이다.

 

Dockerfile.multistage빌드 구성

위의 그림은 멀티 스테이지 빌드이다.

 

이번 파트에서는 이미지가 레이어 구조로 구성되어 있다는 것을 학습했다. 레이어 구조이기 때문에 스토리지 공간도 효율적으로 사용할 수 있고 이미지를 컨테이너로 실행할 때도 아주 빠르게 실행할 수 있다는 것을 학습했다. 그리고 이미지를 만드는 방법인 커밋과 빌드 방식에 대해서 학습했다. 커밋 방식으로 실제로 이미지를 만들어 보고 똑같은 과정을 이미지 빌드를 사용해서 간편하게 이미지를 생성했다. 그리고 이미지를 빌드할 때 사용되는 파일인 빌드 컨텍스트에 대해서 학습했다. 빌드 컨텍스트로 전달되는 파일 목록을 관리하기 위한 .dockerignore 파일도 확인했다. 그리고 도커 파일을 작성하기 위해서 다양한 지시어들을 학습했다. 마지막으로 실행에 사용되는 이미지의 크기를 줄이기 위해서 멀티 스테이징 빌드를 활용하는 방법에 대해 학습했다.

 

이제 도커에 대한 기본적인 개념과 꼭 필요한 기술들을 다 학습했다고 볼 수 있다. 이제는 실무에서 애플리케이션을 어떻게 이미지로 활용하고 이 이미지로 실행한 컨테이너들이 어떻게 서로 상호작용을 하면서 구성되는지 조금 더 실무에 가까운 기술들을 배울 것이다. 다음 파트에서는 실제로 애플리케이션 환경을 구성하기 위해서 데모 애플리케이션을 프론트엔드, 백엔드, 데이터베이스로 각각 나눠서 컨테이너 환경을 구성해보자.