이 글은 [2024 NEW] 개발자를 위한 쉬운 도커 강의를 듣고 작성한 글입니다! 모든 강의자료 이미지 출처는 해당 강사님께 있습니다.
멀티 스테이지
멀티 스테이지 빌드는 두 개의 베이스 이미지를 활용하는 방법이다. 보통 애플리케이션을 빌드하는 과정에서 만들어지는 파일들이 용량을 많이 차지한다. 이 파일들은 실제 애플리케이션이 실행되는 데는 사용되지 않기 때문에 빌드에 사용되는 이미지와 실행에 사용되는 이미지로 나눈다. 멀티 스테이지 빌드를 잘 사용하면 애플리케이션이 실행되는 이미지의 크기를 줄일 수 있다.
백엔드 SpringBoot Application 이미지 구성
자바로 개발된 소프트웨어는 jar나 war로 소스코드를 실행 가능한 아티팩트로 만들 수 있다. jar파일로 실행시키기 위해서는 OS에 java runtime이 설치되어 있어야 한다. 소스코드를 애플리케이션으로 빌드하려면 maven 혹은 gradle 빌드 도구가 필요하다. 여기서는 maven을 활용한다. mvn clean package로 애플리케이션 빌드를 진행한다. 애플리케이션 아티팩트 파일인 app.jar 파일이 만들어진다.
단일 스테이지 빌드
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"]
FROM
베이스 이미지인 maven:3.6-jdk-11에는 빌드를 할 수 있는 maven과 자바 11 버전이 설치되어 있다.
WORKDIR
WORDIR로 작업 디렉토리를 app으로 이동한다. pom.xml과 src 디렉토리 모두 복사, pom.xml에는 라이브러리 정보가 있기 때문에 이 파일이 있어야만 애플리케이션 빌드가 가능하다. src에는 실제 소스코드가 있다.
RUN
RUN 명령어로 jar 파일 생성, jar 파일 생성 위치는 target이라는 폴더 내에 존재하게 된다.
내부에서 만들어진 jar 파일을 app.jar 파일로 복사한다.
EXPOSE, CMD
8080 포트를 사용하며 CMD 지시어에는 자바 애플리케이션을 실행하는 명령어를 입력한다.
단일 스테이지 빌드를 하면 실제 애플리케이션을 실행할 때 필요하지 않은 파일들이 만들어진다. 예를 들어, maven 도구는 애플리케이션을 빌드할 때만 사용되며 애플리케이션이 실행되는 데에는 필요하지 않다. maven 도구의 사이즈가 크기 때문에 실제 애플리케이션 이미지 사이즈도 커진다. 실행용 이미지의 크기가 커지면 이미지를 전송하고 다운로드 받는 시간이 더 걸리기 때문에 애플리케이션을 실행하는 시간에 영향을 줄 수 있다.
멀티 스테이지 빌드
애플리케이션을 빌드하는 과정 (빌드 스테이지) 과 애플리케이션을 실행하는 과정 (실행 스테이지) 으로 나눌 수 있다. 빌드 스테이지에서는 jar 파일을 만들고, 실행 스테이지에서는 자바 런타임만 있는 이미지를 가져와서 결과물인 jar 파일만 복사하여 애플리케이션을 실행한다. 애플리케이션 빌드 시에는 maven 도구와 소스코드가 필요하다. 애플리케이션을 실행 시에는 자바 런타임과 jar 파일이 필요하다.
Dockerfile.multistage에 다음과 같이 작성한다.
# 첫번째 단계: 빌드 환경 설정
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"]
위 Dockerfile에는 FROM이 두 개가 있다. FROM이 2개 있으면, 도커가 2개의 컨테이너를 동시에 생성하고, 첫 번째 컨테이너에서 만들어진 파일을 두 번째 컨테이너로 복사해 올 수 있다. openjdk:11-jre-slim은 자바 애플리케이션 실행에 필요한 자바 런타임만 가지고 있는 이미지이다.
COPY의 --from=build
AS build 부분이 maven 이미지를 사용한 스테이지에 이름을 지정해 놓은 것이다. 다른 스테이지에서 파일을 가져올 때는 --from 옵션을 사용하여 스테이지의 AS 뒤에 있는 이름을 지정하면 된다. 빌드 컨텍스트에서 가져오는 것이 아니라, build 라고 이름 지어진 maven stage에서 파일을 가져오는 것이다.
싱글 스테이지와 멀티 스테이지 실습
다음 명령어로 각각 이미지를 빌드한다.
docker build -f Dockerfile.singlestage -t javappsingle .
docker build -f Dockerfile.multistage -t javaappmulti .
빌드된 이미지를 조회하여 용량을 확인해보면 확연한 차이를 볼 수 있다.
docker image ls javaappsingle
docker image ls javaappmulti
정리
이미지에 복사해온 소스코드와 외부 라이브러리 파일들까지 포함되어 있어 불필요한 파일들이 많이 포함되어 있다. mvn은 빌드에만 사용되므로 애플리케이션을 실행하는 베이스 이미지도 불필요하게 커진 상태이다. 단일 스테이지 빌드를 두 단계로 쪼개서 첫 번째 이미지는 빌드에 필요한 maven만 포함되어 있는 maven 이미지만 사용하고, 두 번째 이미지에는 자바 런타임만 포함되어 있는 open jdk 이미지를 사용했다. 첫 번째 maven 이미지에서 소스코드를 복사하고 소스코드를 애플리케이션으로 빌드하고 결과물로 만든 아티팩트인 app.jar 를 실행에 사용하는 open jdk 이미지에서 복사해 온 것이다.
멀티 스테이징을 잘 사용하면 애플리케이션 이미지를 크게 줄일 수 있다.
'Docker' 카테고리의 다른 글
Leafy 애플리케이션 구성 (0) | 2024.02.29 |
---|---|
클라우드 네이티브 애플리케이션 (0) | 2024.02.27 |
Dockerfile 지시어 (1) | 2024.02.27 |
빌드 컨텍스트 (0) | 2024.02.20 |
이미지 커밋과 빌드 (0) | 2024.02.20 |