본문으로 건너뛰기

도커를 이용한 NestJS 배포

NestJS 앱을 Docker 멀티 스테이지 빌드로 컨테이너화하는 Dockerfile. 빌드 단계와 실행 단계를 분리해 이미지 크기를 최소화한다.

멀티 스테이지 빌드 전략

빌드 단계 (builder):

  • Node 16 Alpine 이미지 기반
  • npm/yarn 최신 버전으로 업그레이드
  • 의존성 설치 및 TypeScript 컴파일
  • node 유저로 권한 분리

실행 단계:

  • 빌드 결과물(dist/)만 복사해 이미지 경량화
  • 불필요한 devDependencies 제외
  • Alpine 환경에서 필요한 네이티브 라이브러리 설치

Dockerfile

FROM node:16-alpine as builder

RUN npm install -g --force npm@latest yarn@latest

ENV NODE_ENV build
RUN mkdir /app && chown -R node:node /app
WORKDIR /app

COPY package.json yarn.lock nest-cli.json tsconfig.* bin/ src/ /app

RUN chown -R node:node /app

USER node
RUN yarn install --frozen-lockfile --force \
&& yarn build

# ---

FROM node:16-alpine

ENV NODE_ENV production
# ENV TNS_ADMIN /app/secrets/
# ENV LD_LIBRARY_PATH=/lib

RUN sed -i 's/http\:\/\/dl-cdn.alpinelinux.org/https\:\/\/alpine.global.ssl.fastly.net/g' /etc/apk/repositories
RUN apk --no-cache add libaio libnsl libc6-compat curl

USER node
WORKDIR /app
ENV NODE_ENV production

COPY --from=builder /app/package*.json /app/
COPY --from=builder /app/node_modules/ /app/node_modules/
COPY --from=builder /app/dist/ /app/dist/
COPY --from=builder /app/bin/ /app/bin/

ENTRYPOINT APP_VERSION=$(/app/bin/get_version_script.sh) node dist/src/main.js

주요 포인트

  • --frozen-lockfile: yarn.lock과 일치하지 않으면 빌드 실패 → 재현 가능한 빌드 보장
  • USER node: root 권한 없이 실행 → 컨테이너 보안 강화
  • libaio libnsl libc6-compat: Oracle DB 등 네이티브 바인딩이 필요한 경우 추가 라이브러리
  • ENTRYPOINT: 앱 버전을 환경 변수로 주입해서 실행

빌드 및 실행

# 이미지 빌드
docker build -t my-nestjs-app .

# 실행 (포트 3000)
docker run -p 3000:3000 my-nestjs-app

# 환경변수 주입
docker run -p 3000:3000 -e DATABASE_URL=... my-nestjs-app