📘
NestJSをDocker(Alpine)で動かす
NestJS のプロジェクトを作成する
任意のディレクトリで以下のコマンドを実行します。
npm i -g @nestjs/cli
nest new .
プロジェクトを作成したら、とりあえず動かしてみます。
npm run start:dev
以下のコマンドを実行すると Hello World!
が返ってきます。
curl http://localhost:3000/
Dockerfile を用意する
touch Dockerfile
Dockerfile
FROM node:19.8.1-alpine3.17 as base
WORKDIR /app
RUN chown -R node:node /app
RUN apk add --no-cache bash tini tzdata \
&& ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
&& echo "Asia/Tokyo" > /etc/timezone \
&& apk del tzdata \
&& rm -rf /var/cache/apk/*
ENV TZ=Asia/Tokyo
FROM base as development
COPY package*.json ./
RUN npm i
COPY . .
USER node
EXPOSE 8080
ENTRYPOINT ["tini", "--", "npm", "run", "start:dev"]
FROM base as build
COPY package*.json ./
COPY /app/node_modules ./node_modules
COPY . .
RUN npm run build
ENV NODE_ENV=production
RUN npm i --omit=dev
USER node
FROM base as production
ENV NODE_ENV=production
COPY /app/node_modules ./node_modules
COPY /app/dist ./dist
EXPOSE 8080
USER node
ENTRYPOINT ["tini", "--", "node", "dist/main.js"]
Docker で NestJS を動かす
開発用のイメージをビルドします。
docker build . --target development -t nestapp:dev
コンテナを立ち上げます。
docker run -p 3000:3000 nestapp:dev
Hello World
が返ってくることを確認します。
curl http://localhost:3000
本番環境用のコンテナもビルドしてみます。
docker build . --target production -t nestapp:prod
コンテナを立ち上げます。
docker run -p 3000:3000 nestapp:prod
同じく curl
で Hello World が返ってくることを確認します。
curl http://localhost:3000
次に、 docker compose で Docker コンテナを動かしてみます。
touch docker-compose.yml
docker-compose.yml
は以下のようにします。
docker-compose.yml
version: "3.8"
services:
app:
build:
context: .
target: development
volumes:
- .:/app
ports:
- "3000:3000"
以下のコマンドで docker compose を立ち上げます。
docker compose up
curl
で Hello World が返ってくることを確認します。
curl http://localhost:3000
最後に、trivy
を使って脆弱性がないか確認します。
brew install trivy
以下のコマンドを実行します。
trivy image nestapp:prod
結果、脆弱性がないことが確認できました。
nestapp:prod (alpine 3.17.2)
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
インターネット上では、「安易に alpine を使うのをやめて、 slim や distroless を使え」という記事が多かったのですが、 slim
や distroless
でビルドすると、どうしても trivy
の脆弱性検査に引っかかってしまったので、結局 alpine
をベースにしました(2023 年 3 月時点)
Discussion