+1

Docker hóa ứng dụng NestJS: Hướng dẫn chi tiết từ A đến Z

Bài viết này sẽ hướng dẫn bạn cách đóng gói ứng dụng NestJS vào một container Docker, giúp ứng dụng chạy ổn định trên nhiều môi trường khác nhau. Cùng bắt đầu nào!

Bước 1: Thiết lập Dockerfile

Đầu tiên, chúng ta cần tạo một file Dockerfile trong thư mục gốc của dự án NestJS. File này sẽ chứa các hướng dẫn để build Docker image.

Dưới đây là một Dockerfile cơ bản:

# Use Node.js version 20 as the base image
FROM node:20

# Set the working directory in the container
WORKDIR /usr/src/app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Build the application
RUN npm run build

# Run the application
CMD ["node", "dist/main.js"]

Dockerfile này thực hiện các tác vụ sau:

  • Sử dụng Node.js phiên bản 20 làm base image.
  • Thiết lập thư mục làm việc thành /usr/src/app.
  • Sao chép package.jsonpackage-lock.json vào thư mục làm việc.
  • Cài đặt các dependencies bằng npm install.
  • Sao chép phần còn lại của mã ứng dụng vào container.
  • Build ứng dụng bằng npm run build.
  • Chỉ định lệnh để chạy ứng dụng với node dist/main.js.

Tạo một file .dockerignore để loại trừ các file không cần thiết khỏi Docker image.

node_modules
npm-debug.log
dist
.git
.env
*.md
.gitignore

Bước 2: Kiểm tra Docker Container cục bộ

Bây giờ, hãy kiểm tra Docker image cục bộ để đảm bảo mọi thứ hoạt động như mong đợi.

Build Docker Image: Mở terminal tại thư mục gốc của dự án và chạy lệnh:

   docker build -t nest-app .

Lệnh này sẽ build Docker image và gắn tag nest-app cho nó.

Chạy Docker Container: Sau khi build image, bạn có thể chạy nó bằng lệnh:

   docker run -p 3000:3000 nest-app

Lệnh này sẽ khởi động một container mới từ image nest-app và ánh xạ cổng 3000 của container với cổng 3000 trên máy cục bộ của bạn.

Kiểm tra ứng dụng: Mở trình duyệt web và truy cập http://localhost:3000. Nếu mọi thứ được thiết lập chính xác, bạn sẽ thấy ứng dụng NestJS của mình đang chạy.

Bước 3: Tối ưu hóa cho môi trường Production

Để tối ưu hóa Dockerfile cho môi trường production, chúng ta sẽ thực hiện một vài thay đổi để giảm kích thước image và cải thiện bảo mật.

Sử dụng Alpine Node Images: Các Alpine image nhỏ hơn và hiệu quả hơn. Cập nhật base image thành:

   FROM node:20-alpine

Thiết lập biến môi trường NODE_ENV: Thiết lập NODE_ENV thành production để tối ưu hóa ứng dụng cho môi trường production:

   ENV NODE_ENV production

Sử dụng npm ci thay vì npm install: npm ci đáng tin cậy hơn cho các môi trường tự động như Docker builds. Thay thế RUN npm install bằng:

   RUN npm ci

Thêm hướng dẫn USER: Chạy ứng dụng với tư cách là người dùng không phải root để bảo mật tốt hơn. Thêm đoạn mã sau sau khi cài đặt dependencies:

   USER node

Sử dụng Multistage Builds: Multistage builds cho phép bạn tạo image cuối cùng nhỏ hơn bằng cách tách biệt môi trường build và runtime. Dưới đây là ví dụ về một Multistage Dockerfile:

   # Development stage
   FROM node:20-alpine AS development
   WORKDIR /usr/src/app
   COPY package*.json ./
   RUN npm ci
   COPY . .
   USER node

   # Build stage
   FROM node:20-alpine AS build
   WORKDIR /usr/src/app
   COPY package*.json ./
   COPY --from=development /usr/src/app/node_modules ./node_modules
   COPY . .
   RUN npm run build
   ENV NODE_ENV production
   RUN npm ci --only=production && npm cache clean --force
   USER node

   # Production stage
   FROM node:20-alpine AS production
   WORKDIR /usr/src/app
   COPY --from=build /usr/src/app/node_modules ./node_modules
   COPY --from=build /usr/src/app/dist ./dist
   CMD ["node", "dist/main.js"]

Thiết lập này sử dụng ba giai đoạn:

  • development: Dành cho phát triển cục bộ với tất cả các dependencies.
  • build: Build ứng dụng cho production.
  • production: Giai đoạn cuối cùng chạy bản build production.

Bước 4: Xây dựng lại và chạy Image đã tối ưu hóa

Sau khi cập nhật Dockerfile, hãy xây dựng lại image:

docker build -t nest-app .

Sau đó, chạy container đã được tối ưu hóa:

docker run -p 3000:3000 nest-app

Kiểm tra kích thước của image mới bằng lệnh:

docker images

Bạn sẽ thấy kích thước image giảm đáng kể, giúp nó hiệu quả hơn khi sử dụng trong môi trường production.

Khắc phục sự cố thường gặp

  • Lỗi: Cannot find module 'webpack': Đảm bảo bạn đang sử dụng đúng phiên bản Node.js trong base image. Ví dụ: sử dụng FROM node:20-alpine thay vì FROM node:14-alpine.
  • Lỗi: nest command not found: Điều này thường xảy ra nếu Nest CLI chưa được cài đặt. Trong multistage build, hãy đảm bảo bạn sao chép thư mục node_modules từ giai đoạn development, nơi CLI được cài đặt.

Sử dụng các trình quản lý gói khác nhau

Nếu bạn đang sử dụng pnpm thay vì npm, Dockerfile của bạn sẽ hơi khác một chút. Dưới đây là một ví dụ:

# Development stage
FROM node:20 AS development
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
WORKDIR /usr/src/app
COPY pnpm-lock.yaml ./
RUN pnpm fetch --prod
COPY . .
RUN pnpm install
USER node

# Build stage
FROM node:20 AS build
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
WORKDIR /usr/src/app
COPY pnpm-lock.yaml ./
COPY --from=development /usr/src/app/node_modules ./node_modules
COPY . .
RUN pnpm build
ENV NODE_ENV production
RUN pnpm install --prod
USER node

# Production stage
FROM node:20-alpine AS production
WORKDIR /usr/src/app
COPY --from=build /usr/src/app/node_modules ./node_modules
COPY --from=build /usr/src/app/dist ./dist
CMD ["node", "dist/main.js"]

Sử dụng Fastify với NestJS

Nếu bạn đang sử dụng Fastify thay vì Express, bạn sẽ cần sửa đổi file main.ts để lắng nghe trên 0.0.0.0:

import { NestFactory } from '@nestjs/core';
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter(),
  );
  await app.listen(process.env.PORT || 3000, '0.0.0.0');
}
bootstrap();

Vậy là xong! Bây giờ bạn đã có một ứng dụng NestJS được docker hóa và tối ưu hóa cho môi trường production. Nếu bạn muốn triển khai ứng dụng NestJS của mình, hãy xem sliplane.io.


All rights reserved

Bình luận

Đăng nhập để bình luận
Avatar
+1
Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí