⚡ NestJS Gateway Dockerfile 최적화하기
NestJS 마이크로서비스를 실무에 배포할 때, Dockerfile 최적화는 필수입니다. 단순히 "잘 동작한다"에서 끝나는 것이 아니라,
이미지 빌드 속도 ⏱, 컨테이너 크기, 실행 성능 ⚡까지 모두 고려해야 하기 때문이죠.
1. 기존 Dockerfile의 문제점 ⭕
처음 보여준 Dockerfile은 이렇게 작성되어 있었습니다:
FROM node:alpine AS development WORKDIR /usr/src/app COPY package.json ./ COPY pnpm-lock.yaml ./ # PNPM 설치하기 RUN npm i-g pnpm # Dependency 설치하기 RUN pnpm i #나머지 파일/폴더 복사해오기 COPY . . CMD ["pnpm", "start:dev", "gateway"]
➡️ 이 Dockerfile은 기본적으로는 동작하지만, 문제가 있습니다:
캐싱 불가능: 모든 소스를 한 번에 복사하기 때문에 작은 변경에도 모든 빌드가 다시 실행됩니다.
불필요한 파일 복사: 테스트 코드, 설정 파일, 로컬 전용 파일까지 전부 들어갑니다.
개발 환경과 배포 환경 구분 없음: production 모드 최적화가 전혀 되어 있지 않습니다.
즉, 빠르게 개발 테스트하는 데는 좋지만, 운영 환경 배포에는 비효율적이라는 거죠. ⚠️
2. 최적화된 Dockerfile ✅
최적화된 버전은 다음과 같이 크게 development와 production 두 개의 스테이지로 분리합니다:
FROM node:alpine AS development # 개발 환경용 베이스 이미지 (가볍고 빠른 alpine) WORKDIR /usr/src/app # 컨테이너 내부 작업 디렉토리 지정 COPY package*.json ./ # 패키지 메타 파일 먼저 복사 (캐싱 최적화) COPY pnpm-lock.yaml ./ COPY tsconfig.json tsconfig.json # 타입스크립트 설정 파일 복사 COPY nest-cli.json nest-cli.json # Nest CLI 설정 파일 복사 # PNPM 설치하기 RUN npm i -g pnpm # 전역으로 pnpm 설치 # Dependency 설치하기 RUN pnpm i # 모든 의존성 설치 (devDependencies 포함) # 빌드에 필요한 파일만 복사 COPY proto /proto # 프로토콜 버퍼 파일 복사 COPY apps/gateway apps/gateway # 게이트웨이 앱 소스 복사 COPY libs libs # 공용 라이브러리 복사 RUN pnpm build gateway # 게이트웨이 앱 빌드 실행 CMD ["pnpm", "start:dev", "gateway"] # 개발 모드 실행 커맨드 --- FROM node:alpine AS production # 운영 환경용 베이스 이미지 (더 가볍게) ARG NODE_ENV=production ENV NODE_ENV=${NODE_ENV} # 운영 모드 환경 변수 설정 WORKDIR /usr/src/app # 작업 디렉토리 지정 COPY package.json ./ # 필요한 패키지 파일만 복사 COPY pnpm-lock.yaml ./ COPY proto /proto # 실행 시 필요한 proto 파일만 복사 RUN npm install -g pnpm # pnpm 전역 설치 RUN pnpm install --prod # 운영용 의존성만 설치 (devDependencies 제외) COPY --from=development /usr/src/app/dist ./dist # 빌드된 결과물만 가져오기 CMD [ "node", "dist/apps/gateway/main" ] # 게이트웨이 앱 운영 모드 실행
➡️ 이 구조의 핵심은 멀티 스테이지 빌드입니다.
3. 멀티 스테이지 빌드의 장점 ⚡
빌드 단계와 실행 단계를 분리
development 단계에서는 TypeScript를 빌드하고, production 단계에서는 빌드된 결과물(dist)만 가져옵니다.
이렇게 하면 최종 이미지 크기가 대폭 줄어듭니다.
의존성 최소화
개발 단계에서는 devDependencies까지 설치 (pnpm i)
운영 단계에서는 dependencies만 설치 (pnpm install --prod)
➡️ 배포 이미지는 더 가볍고, 보안상도 안전합니다.
빌드 캐시 활용
package.json, pnpm-lock.yaml만 먼저 복사하고 설치를 하기 때문에, 소스 코드 변경 시에도 dependency 설치를 다시 하지 않아도 됩니다.
4. 실무 적용 팁 ⭕
빌드 속도 최적화
.dockerignore 파일을 꼭 작성하세요. node_modules, test/, .git 같은 불필요한 파일이 들어가면 이미지 빌드가 느려집니다.
보안 강화
node:alpine 이미지를 사용하면 기본 Debian 이미지보다 훨씬 가볍습니다. 다만, 필요 시 apk add로 패키지를 설치해야 하니 주의하세요.
환경 변수 관리
ARG와 ENV를 잘 구분하세요.
ARG는 빌드 시점에만 사용, ENV는 런타임까지 유지됩니다.
5. 핵심 정리 ✅
기존 Dockerfile 문제점: 캐싱 불가, 불필요한 파일 복사, 개발/운영 구분 없음.
최적화된 Dockerfile 핵심: 멀티 스테이지 빌드 ➡️ 개발과 운영 단계 분리.
이점: 빌드 속도 향상, 이미지 크기 최소화, 보안 강화.
➡️ 결론: NestJS 같은 대규모 프로젝트는 반드시 멀티 스테이지 빌드를 적용해야 합니다.
6. 추가 학습 포인트 ⚡
Docker BuildKit 사용법 (DOCKER_BUILDKIT=1)
CI/CD 환경에서 docker-compose와 멀티 스테이지 빌드 조합하기
distroless 이미지로 보안 강화하기 (Google 제공)
댓글 ( 0)
댓글 남기기