한눈에 보기
- 무거운 Docker 이미지를 멀티스테이지 빌드로 수백 MB → 수십 MB로 줄이는 법.
- 핵심은 빌드 도구는 빌드 단계에만, 최종 이미지엔 실행에 필요한 것만.
- 경량 베이스 + .dockerignore + 레이어 정리로 push·pull·콜드스타트가 빨라집니다.
이미지가 크면 빌드·푸시·배포가 느리고, ACR 저장비와 노드 디스크도 잡아먹습니다. 대부분의 비대함은 ‘빌드 도구와 소스를 최종 이미지에 그대로 남겨서’ 생깁니다. 멀티스테이지로 분리하면 극적으로 줄어듭니다.
멀티스테이지 빌드란
한 Dockerfile에 빌드용 스테이지와 실행용 스테이지를 나눠 두고, 최종 이미지엔 빌드 결과물만 복사합니다. 컴파일러·node_modules·캐시 등은 최종 이미지에 포함되지 않습니다.
# 1) 빌드 스테이지
FROM node:20 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 2) 실행 스테이지 (가벼운 베이스)
FROM node:20-slim
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY package*.json ./
RUN npm ci --omit=dev
CMD ["node","dist/main.js"]
이미지 줄이는 체크리스트
| 기법 | 효과 | 주의 |
|---|---|---|
| 멀티스테이지 | 빌드 도구 제거(가장 큼) | COPY –from 경로 정확히 |
| slim/alpine 베이스 | 베이스 수백 MB↓ | alpine은 일부 라이브러리 호환성 확인 |
| .dockerignore | node_modules·.git 제외 | 빌드 컨텍스트 축소 |
| –omit=dev / prod only | 개발 의존성 제거 | 런타임 필요 패키지 누락 주의 |
| 레이어 합치기 | 중간 캐시 제거 | 가독성과 균형 |
.dockerignore부터 챙기기
의외로 가장 쉬운 절감입니다. node_modules, .git, 로그, 로컬 빌드 산출물을 빌드 컨텍스트에서 빼면 빌드도 빨라지고 불필요한 파일이 이미지에 섞이지 않습니다.
# .dockerignore
node_modules
.git
*.log
dist
.env
흔한 실수
- 빌드와 실행을 한 스테이지에 — 컴파일러·캐시가 그대로 남아 비대해집니다.
- alpine으로 무작정 교체 — glibc 의존 패키지가 깨질 수 있으니 테스트하세요.
- .dockerignore 누락 — 거대한 node_modules가 통째로 들어갑니다.
자주 묻는 질문(FAQ)
- Q. alpine이 항상 정답인가요? A. 아닙니다. 호환성 이슈가 있으면 slim 계열이 안전합니다.
- Q. 이미지 크기는 어떻게 확인하나요? A.
docker images또는docker history로 레이어별 용량을 봅니다. - Q. 빌드 캐시를 활용하려면? A. 자주 안 바뀌는 의존성 설치를 COPY 소스보다 위에 두세요.
마치며
멀티스테이지 + 경량 베이스 + .dockerignore, 이 세 가지만 적용해도 대개 이미지가 절반 이하로 줄어듭니다. 작은 이미지는 배포 속도와 비용에 그대로 보답합니다.