네스트 프로젝트를 생성하는 명령어를 입력합니다.
[참고] 다음의 명령어는 nest가 글로벌로 이미 설치된 경우에 실행되는 명령어입니다.
$ nest new [프로젝트명]
$ nest new nestjs-prisma
도커 이미지를 빌드하기 위한 설정을 작성할 Dockerfile을 생성하는 명령어를 입력합니다.
아래의 명령어를 입력할 때 파일명을 확장자 없이 Dockerfile
그대로 작성해야 함에 유의합니다.
$ touch Dockerfile # 대문자 D 소문자 f임에 유의
###################
# 로컬 development 단계
###################
# 베이스 이미지
FROM node:18-alpine AS development
# app 디렉토리 생성
WORKDIR /usr/src/app
# package.json과 package-lock.json 둘다 카피하기 위해서 와일드 카드를 사용합니다.
# 종속성을 가장 먼저 카피하는 이유?
# 코드가 변경될 때마다 npm i를 다시 실행하는 것을 방지합니다.
COPY --chown=node:node package*.json ./
# 종속성 설치
RUN npm ci
#소스 번들링
COPY --chown=node:node . .
# root 유저가 아닌 이미지의 node user 사용
USER node
# RUN npm run start:dev
# CMD [ "ts-node","main.ts", "echo","🚀 server is running 🚀"]
###################
# production 단계를 위한 build 단계
###################
FROM node:18-alpine AS build
# ARG NODE_ENV=production
# ENV NODE_ENV=${NODE_ENV}
WORKDIR /usr/src/app
COPY --chown=node:node package*.json ./
# npm run build를 실행하기 위해서 nest cli에 접근가능해야 합니다.
# nest cli는 dev 종속성입니다.
# 앞서 development 빌드에서 npm ci를 실행하여 모든 종속성을 설치했기 때문에
# development 이미지에서 build 이미지로 node_modules 디렉토리를 카피 할 수 있습니다.
COPY --chown=node:node --from=development /usr/src/app/node_modules ./node_modules
COPY --chown=node:node . .
# production 번들을 생성할 build 커맨드 실행
RUN npm run build
# 노드 환경 변수 설정
ENV NODE_ENV production
# npm ci를 실행하여 존재하는 node_modeuls 디렉토리 제거
# --omit=development를 전달하여 production 종속성만 설치되도록 합니다.
# node_modules 디렉토리가 가능한한 최적화되도록 합니다.
RUN npm ci --omit=development && npm cache clean --force
USER node
###################
# PRODUCTION 단계
###################
FROM node:18-alpine AS production
# build 이미지로부터 production 이미지에 번들된 코드를 카피합니다.
COPY --chown=node:node --from=build /usr/src/app/node_modules ./node_modules
COPY --chown=node:node --from=build /usr/src/app/dist ./dist
# production build를 사용하여 서버를 시작합니다.
CMD ["node", "dist/main.js"]
이미지 빌드 시 제외될 파일들을 작성할 dockerignore 파일을 설치합니다.
$ touch .dockerignore
# /dockerignore
Dockerfile
.dockerignore
node_modules
dist
docker-compose.yml 파일은 컨테이너 내부에서 이미지를 어떻게 실행시킬지에 대한 지시를 나타냅니다.
services:
api:
build:
dockerfile: Dockerfile
context: .
# dockerfile에서 로컬에서 필요로 하지 않는 단계들을 무시하고 오직 development 단계만을 빌드할 것을 나타냅니다.
target: development
volumes:
# 현재 경로와 컨테이너 내부의 /usr/src/app 디렉토리를 볼륨 마운팅할 것을 나타냅니다.
# 데이터가 유지되고, 핫 리로딩을 실행할 부분을 나타냅니다.
- .:/usr/src/app
# 도커에게 컨테이너 내부로 .env 파일을 로드해야 함을 알려줍니다.
env_file:
- .env
# 도커에게 이미지의 development 단계에 대한 npm run start:dev 명령어를 실행해야 함을 알려줍니다.
command: npm run start:dev
ports:
- ${PORT}:3000
그럼 작성한 Dockerfile을 바탕으로 이미지를 빌드해보겠습니다.
경로 .
를 작성하여 기본적으로 현재 경로에서 Dockerfile
을 찾아서 빌드할 것을 안내합니다.
$ docker build -t nestjs-prisma .
# -t 를 통해 tag 설정
[+] Building 4.2s (8/13)
=> [internal] load build definition from Docke 0.0s
=> => transferring dockerfile: 454B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/libr 2.8s
=> [auth] library/node:pull token for registry 0.0s
=> CANCELED [production 1/6] FROM docker.io/li 1.2s
=> => resolve docker.io/library/node:18.15.0-a 0.0s
=> => sha256:47d97b93629d9461d 1.43kB / 1.43kB 0.0s
=> => sha256:b72efe9f0095ca574 1.16kB / 1.16kB 0.0s
=> => sha256:eef8c5727bcaf118e 6.50kB / 6.50kB 0.0s
=> => sha256:81f6a0834130c130 7.34MB / 47.36MB 1.2s
=> => sha256:aa1d735907bcf7391 2.41MB / 2.41MB 1.1s
=> => sha256:465dcb965cfbe29db4810 446B / 446B 1.1s
=> CANCELED [internal] load build context 1.2s
=> => transferring context: 5.92MB 1.2s
=> ERROR FROM docker.io/library/developemnt:la 1.2s
=> => resolve docker.io/library/developemnt:la 1.2s
=> [auth] library/developemnt:pull token for r 0.0s
------
> FROM docker.io/library/developemnt:latest:
------
failed to load cache key: pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
빌드된 이미지를 바탕으로 컨테이너를 생성 후 실행하는 명령어입니다
$ docker container run -dit nest-prisma --name nestjs-prisma -p 8888:80 --rm
# --name을 통해 컨테이너 명을 nestjs-prisma로 설정하였습니다.
# dit 플래그를 통해 백그라운드 실행, interactive 모드, ttl로 컨태이너를 실행합니다.
# -p 즉, --publish를 통해 포트포워딩을 설정하였습니다.
# --rm을 통해 컨테이너 중지 시마다 컨테이너를 삭제할 것을 설정하였습니다.