핵심 요약
이미지가 큰 건 빌드 도구·devDependencies·소스가 최종 이미지에 다 들어가서다. 멀티스테이지 빌드로 "빌드 단계"와 "실행 단계"를 분리해 결과물만 복사하고, slim/alpine 베이스와 .dockerignore를 쓰면 용량이 크게 준다.
1. 멀티스테이지 예
FROM node:22 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-slim # 실행용 가벼운 베이스
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
CMD ["node","dist/server.js"]
2. 추가 절감
| 기법 | 효과 |
|---|---|
| npm ci --omit=dev | devDeps 제외 |
| .dockerignore | node_modules·.git 제외 |
| 레이어 순서(deps 먼저) | 캐시 적중률↑ |
3. 함정
- COPY . . 을 먼저 하면 소스 한 줄만 바뀌어도 npm install 캐시 무효화 — package.json 먼저 복사
- alpine은 glibc가 아니라 일부 네이티브 모듈 문제 — slim이 무난한 절충
- 빌드 산출물만 복사하고 소스·캐시는 두고 와라
자주 묻는 질문
멀티스테이지가 왜 작아지나요?
최종 이미지에는 마지막 스테이지만 남습니다. 컴파일러·devDependencies가 들어간 빌드 스테이지는 버려지고 결과물만 복사되므로 가벼워집니다.
레이어 캐시는 어떻게 잘 쓰나요?
자주 안 바뀌는 것(package.json→install)을 위에, 자주 바뀌는 소스 복사를 아래에 두면, 소스 변경 시에도 의존성 설치 레이어가 캐시됩니다.

댓글 0