Skip to main content

도커를 이용한 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