Multi-stage Build
Multi-stage Build는 하나의 Dockerfile 안에서 빌드용 환경과 실행용 환경을 분리하는 패턴입니다. 앞단 스테이지에서 컴파일과 테스트를 수행하고, 마지막 스테이지에는 실행에 꼭 필요한 산출물만 남깁니다.
▶아키텍처 다이어그램
📊 데이터 흐름 다이어그램점선 애니메이션은 데이터 또는 요청의 흐름 방향을 나타냅니다
단일 스테이지 Dockerfile로 빌드하면 컴파일러, 패키지 캐시, 테스트 도구까지 최종 이미지에 남기 쉽습니다. 그러면 이미지가 커지고 전송이 느려지며, 실제 실행에는 필요 없는 도구가 운영 환경에 포함됩니다. 배포 속도와 보안, 디버깅 난이도가 함께 나빠지는 구조입니다.
초기 Docker 사용자는 빌드와 실행을 같은 컨테이너 안에서 처리하곤 했습니다. 하지만 애플리케이션이 커질수록 '빌드에 필요한 것'과 '운영에 필요한 것'이 크게 다르다는 점이 분명해졌습니다. Multi-stage Build는 이 차이를 같은 Dockerfile 안에서 선언적으로 분리하도록 만든 진화입니다.
첫 번째 스테이지는 SDK, 컴파일러, 테스트 도구를 포함한 무거운 환경일 수 있습니다. 여기서 생성된 바이너리나 `dist/` 결과물만 `COPY --from=builder`로 마지막 스테이지에 옮기면, 최종 이미지는 훨씬 작고 단순해집니다. 즉 스테이지는 시간 순서이면서도, 동시에 '무엇을 남길 것인가'를 거르는 필터 역할을 합니다.
Multi-stage Build와 Dockerfile은 둘 다 이미지를 어떻게 만들지 적는 같은 문맥에 있지만, Multi-stage Build는 Dockerfile 밖의 별도 도구가 아니라 그 안에서 여러 스테이지를 운영하는 패턴입니다. Layer와도 함께 이미지 최적화에 관여하지만, Layer가 각 단계의 캐시와 누적을 다룬다면 Multi-stage Build는 어떤 산출물만 최종 이미지에 남길지 정합니다. 같은 스테이지 안의 재빌드 비용이 고민이면 레이어 설계를 먼저 보고, 빌드 도구와 중간 산출물이 운영 이미지에 남는 것이 문제라면 Multi-stage Build를 적용할 시점입니다.
프런트엔드 빌드에서는 Node 이미지에서 정적 파일을 만들고 마지막에는 그 결과만 경량 웹 서버 이미지에 복사하는 식이 흔합니다. 백엔드에서도 빌드 도구가 큰 언어일수록 이미지 크기와 취약점 수를 함께 줄이는 실질적 수단이 됩니다. 반대로 빌드 산출물이 거의 없거나 빌드 환경과 실행 환경이 거의 같은 작은 서비스라면, 스테이지를 나누는 이득이 크지 않고 Dockerfile만 더 길어질 수 있습니다.