도커 이미지 멀티 스테이지 빌드 - 도커 이미지 용량 최적화가 필요하신가요?
안녕하세요. 이번에는 도커 이미지 멀티 스테이지 빌드에 대해서 간단히 정리하려고 합니다.
도커 이미지를 빌드하다 보면 이미지의 용량이 기하급수적으로 증가하게 되는데요.
- 몇백 MB짜리 이미지가 수십 GB까지 이미지로 변한 것도 봤습니다 ㅎㄷㄷ
로컬 환경에서 개발하는 경우라면 이미지가 계속해서 유지되는 경우가 많기 때문에 크게 신경을 안 쓸 수도 있습니다.
하지만 클라우드 환경에서 서비스 배포에 도커 이미지를 사용한다면 시간을 단축시키기 위해서 용량 최적화는 필수라고 생각합니다.
- 사실 도커 이미지 용량이 작으면 이미지 빌드 시간도 짧아지고 여러모로 로컬 환경에서 개발할 때도 편한 점이 많으니 여유가 조금 있다면 용량 최적화는 꼭 진행해보세요 :)
1. 멀티 스테이지 빌드란?
멀티 스테이지 빌드란 빌드가 진행되는 환경을 여러 개로 분리할 수 있다는 것을 의미합니다.
환경을 여러 개로 분리하면 어떤 점이 좋을까요?
golang을 이용해서 프로그램을 빌드하고 실행하는 도커 이미지를 예로 들어보겠습니다.
golang을 이용해서 프로그램을 빌드하기 위해서는 아래 이미지와 같이
1) golang을 포함한 여러 패키지들을 설치해야 하고, 2) golang 라이브러리들을 설치하고, 3) 빌드해야 합니다.

이 과정들을 거치면 도커 이미지의 용량이 상당히 커지게 됩니다.
그런데 도커 이미지의 용량이 꼭 커야만 할까요?
우리가 필요한건 마지막에 실행할 바이너리 프로그램만 있으면 되는데 말이죠!
이럴 때 멀티 스테이지 빌드를 이용하면
golang을 이용해서 프로그램을 빌드한 뒤, 빌드된 바이너리만 용량이 작은 이미지에 옮겨서 실행할 수 있습니다!

P.S.
alpine linux 이미지 같은 경우에는 용량이 3MB로 매우 가볍습니다!

2. 멀티 스테이지 빌드하는 방법
환경을 나누는 방법은 매우 간단합니다. FROM 명령어를 사용하기만 하면 됩니다.
위에서 들었던 예시를 그대로 사용하면 다음과 같습니다.
첫번째 예시는 한 환경만 있어서 FROM 명령어가 1개만 사용됩니다.

하나의 스테이지를 추가하여 도커 이미지 용량을 최적화하는 Dockerfile은 다음과 같습니다.

FROM alpine:latest 명령어를 이용해서 새로운 환경을 만들고
COPY --from=0 /program /program 명령어를 이용해서 이전 환경에서 만든 바이너리를 새로운 환경으로 옮기는 것이 핵심입니다!
- --from=0 이 이전 환경을 의미합니다.
- 만약 환경이 2개보다 더 많을 때에는 환경에 이름을 부여하고 싶어지겠죠? 그럴 때는 FROM golang:latest AS stage1 과 같이 환경에 이름을 부여할 수 있습니다.
참고