멀티 스테이지 빌드란 무엇이고
어떻게 사용하는 것일까?
멀티 스테이지 빌드 (Multi-Stage build)
--
멀티 스테이지 빌드는
Dockerfile에서 두 개의 베이스 이미지를 활용하는 방법을 의미한다.
보통 애플리케이션을 빌드하는 과정에서 만들어지는 파일들이 용량을 많이 차지한다.
하지만 해당 파일들은 실제로 애플리케이션이 실행되는 시점부터는 사용하지 않기 때문에
이미지 빌드에 사용하는 이미지와 실행에 사용하는 이미지로 나누는 것이다.
이렇게 멀티 스테이지 빌드를 잘 활용하면
실제로 애플리케이션이 실행되는 이미지의 크기를 줄일 수 있다.
애플리케이션 빌드 vs 이미지 빌드
애플리케이션 빌드는
소스 코드를 실행 가능한 프로그램으로 만드는 것을 의미
즉, 해당 소스 코드가 실행되기 위해 필요한 라이브러리를 설치하거나 소스 코드를 실행 가능한 프로그램으로
만드는 과정
이미지 빌드
컨테이너로 바로 실행할 수 있는 이미지로 만드는 것을 의미
이미지 빌드과정 안에 애플리케이션 빌드가 포함되어 있다.
--
실습 목표
--
- jar 파일을 실행시키기 위해서는 OS에 자바 런타임이 설치되어 있어야 함
- 소스 코드를 애플리케이션으로 빌드하려면 maven 또는 gradle이라는 빌드 도구가 필요 (maven 사용)
순서
- OS 위에 자바 런타임과 maven 설치
- 해당 애플리케이션의 소스코드를 다운
- "mvn clean package" 라는 maven 명령어로 애플리케이션 빌드 실행
- 애플리케이션 빌드가 끝나면 app.jar 파일이 생성됨
- 해당 애플리케이션(app.jar)을 실행하려면 "java -jar app.jar" 명령어를 사용하여 실행
- 실행된 애플리케이션에 접속하면 결과를 확인 가능
--
멀티 스테이지 빌드 방법을 사용하여 이미지 빌드 과정
--
Dockerfile에 작성한 지시어
베이스 이미지를 지정하는 FROM 지시어를 두 개 작성하여 단계를 구분하였다.
베이스 이미지 설명
- FROM maven:3.6 = maven 빌드 방식의 애플리케이션을 빌드하기 위한 이미지
- FROM openjdk:11-jre-slim = JAVA 애플리케이션 실행에 필요한 자바 런타임만 가진 이미지
지시어 설명
FROM maven:3.6 AS build | Maven 3.6버전의 이미지를 베이스 이미지 지정 즉, maven 빌드 환경 설정 AS 명령어를 통해 현재 빌드 스테이지에 이름을 부여 (이 후 스테이지에서 해당 스테이지를 참조할 수 있도록) |
WORKDIR /app | 현재 작업 디렉토리 위치를 "/app" 디렉토리로 이동 (이후 명령어들은 모두 해당 디렉토리 위치에서 실행됨) |
COPY pom.xml . | 빌드 컨텍스트에서 pom.xml 파일을 컨테이너의 "/app" 디렉토리로 복사 (Maven은 pom.xml 파일을 통해 의존성 및 빌드 설정을 파악) |
COPY src ./src | 빌드 컨텍스트에서 src 폴더를 컨테이너의 "/app/src"디렉토리로 복사 (src 폴더에는 Java 소스 파일들이 포함되어 있다.) |
RUN mvn clean package | Maven을 사용하여 해당 프로젝트를 빌드한다. (clean으로 이전 빌드의 내용들을 삭제하고, packeage는 소스 코드를 컴파일하고 테스트하며 최종적으로 jar 파일을 생성한다.) |
FROM openjdk:11-jre-slim | openjdk 11버전에서 jre slim 버전의 이미지를 베이스 이미지로 지정 jre는 Java 애플리케이션을 실행하기 위한 환경을 제공해준다. |
WORKDIR /app | 현재 작업 디렉토리 위치를 "/app" 디렉토리로 이동 (이후 명령어들은 모두 해당 디렉토리 위치에서 실행됨) |
COPY --from=build /app/target/*.jar ./app.jar | "build" 스테이지(첫 번재 빌드 = "build")에서 생성된 jar 파일을 현재 컨테이너의 "/app.jar" 파일로 복사 |
EXPOSE 8080 | 해당 컨테이너가 수신할 포트는 8080이라고 지정 |
CMD ["java", "-jar", "app.jar"] | 컨테이너가 시작될 때 자동으로 실행되는 명령어 지정 (app.jar 파일을 실행) |
현재 스테이지에 이름을 명시하는 명령어 형식 (FROM 지시어인 베이스 이미지 지정하는 곳에서 사용 가능)
FROM {이미지명} AS {스테이지명}
다른 스테이지에서 파일을 가져오는 명령어 형식
--from={스테이지명} {가져올파일위치} {복사할파일위치}
dockerfile의 동작 과정
"build" 스테이지 (첫 번째 빌드 단계)
- Maven 이미지를 베이스 이미지로 지정 후 Java 애플리케이션의 빌드 환경 설정
(현재 스테이지의 이름을 "build"로 지정) - pom.xml과 src 디렉터리를 복사
- "mvn clean package" 명령어를 통해 jar 파일 생성
jar 파일을 만들면 Maven 이미지의 target 폴더에 jar 파일이 생성된다.
실행 스테이지 (두 번째 빌드 단계)
- openjdk에서 jre slim 버전의 이미지를 베이스 이미지로 지정 후 Java 애플리케이션의 실행 환경 설정
(해당 이미지는 애플리케이션을 실행하기 위한 환경만 제공해 주므로 가벼움) - 이전에 "build" 스테이지에서 생성한 jar 파일을 복사해서 가져옴
- 가져온 jar 파일을 실행
다른 스테이지에서 파일을 가져올 때는
"--from" 옵션을 사용해서 특정 스테이지의 AS 뒤에 명시한 이름을 지정하여 가져오면 된다.
도커 빌드는
도커가 지시어를 읽어서 임시로 컨테이너를 만들고 작업을 자동으로 수행하는 방법이라고 설명했지만
지금처럼 FROM 지시어가 두 개 이상 존재하게 된다면
도커는 이 두 개의 컨테이너를 동시에 생성하고
첫 번째 컨테이너에서 만들어진 파일을 두 번째 컨테이너로 복사해 올 수 있다.
그래서 빌드용으로 따로 만들고 실행용으로 따로 만들어서 효율성 있도록 할 수 있는 것이다.
--
정리
--
첫 번째 이미지는 빌드에 필요한 Maven만 포함하여 이미지를 사용하고
두 번째 이미지는 자바 런타임만 포함되어 있는 OpenJDK 이미지를 사용한다.
그리고 첫 번째 Maven 이미지에 있는 소스 코드(app.jar)를 복사하여 애플리케이션으로 빌드했다.
기존에 이미지를 빌드할 때에는
최종적으로 만들어지는 이미지 안에
빌드 시에만 필요했던 툴, 라이브러리 등이 포함되어 있어서 불필요하게 용량이 컸지만
멀티 스테이지 빌드 방법을 사용하여
빌드용 이미지와 최종적으로 사용하는 이미지를 분리하여 만들어서
최종적으로 사용하는 이미지에 불필요한 파일들을 없애 용량이 가벼워졌다.
--
참고 및 출처
'Docker' 카테고리의 다른 글
Vue.js, Spring Boot, PostgreSQL 컨테이너 구성 및 연결하여 애플리케이션 구현하기 (+실습) (0) | 2024.06.25 |
---|---|
클라우드 네이티브 애플리케이션 (0) | 2024.06.24 |
Dockerfile의 지시어 정리 (0) | 2024.06.21 |
빌드 컨텍스트 (Build Context)란? (0) | 2024.06.20 |
이미지를 만드는(저장) 방법 [ image build ] (+명령어) (+IaC) (+Dockerfile 작성법) (0) | 2024.06.19 |