Hướng Dẫn Docker Hóa Ứng Dụng NestJS 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 và hiệu quả trong nhiều môi trường khác nhau. Hãy theo dõi qua từng bước chi tiết dưới đây!
Bước 1: Thiết lập Dockerfile
Trước tiên, bạn 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 để xây dựng Docker image. Dưới đây là một mẫu Dockerfile cơ bản:
dockerfile
# Sử dụng Node.js phiên bản 20 làm base image
FROM node:20
# Thiết lập thư mục làm việc trong container
WORKDIR /usr/src/app
# Sao chép package.json và package-lock.json
COPY package*.json ./
# Cài đặt các dependencies
RUN npm install
# Sao chép mã ứng dụng còn lại vào container
COPY . .
# Build ứng dụng
RUN npm run build
# Chạy ứng dụng
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 các file
package.json
vàpackage-lock.json
vào thư mục làm việc. - Cài đặt các dependencies với lệnh
npm install
. - Sao chép toàn bộ mã ứng dụng vào container.
- Xây dựng ứng dụng với lệnh
npm run build
. - Chỉ định lệnh chạy ứng dụng bằng
node dist/main.js
.
Bên cạnh đó, bạn cũng nên tạo một file .dockerignore
để loại trừ các file không cần thiết khỏi Docker image:
dockerignore
node_modules
npm-debug.log
dist
.git
.env
*.md
.gitignore
Bước 2: Kiểm tra Docker Container Cục Bộ
Sau khi đã thiết lập Dockerfile, hãy kiểm tra Docker image để đảm bảo mọi thứ hoạt động trơn tru.
Xây dựng Docker Image: Mở terminal tại thư mục gốc của dự án và chạy lệnh:
bash
docker build -t nest-app .
Lệnh này sẽ xây dựng Docker image và gán tag là nest-app
cho nó.
Chạy Docker Container: Sau khi hoàn thành quá trình xây dựng image, bạn có thể chạy container bằng lệnh:
bash
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ủa bạn.
Kiểm tra Ứng Dụng: Mở trình duyệt 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 nhằm giảm kích thước image và cải thiện bảo mật:
- Sử dụng Alpine Node Images: Những image này nhẹ hơn và hiệu quả hơn. Cập nhật базe image thành:
dockerfile
FROM node:20-alpine
- Thiết lập biến môi trường NODE_ENV: Đặt
NODE_ENV
thànhproduction
để tối ưu hóa ứng dụng cho sản xuất:dockerfileENV 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 cài đặt như Docker. Thay thếRUN npm install
bằng:dockerfileRUN npm ci
- Thêm hướng dẫn USER: Chạy ứng dụng với tài khoản không phải root để nâng cao bảo mật. Thêm đoạn mã sau khi cài đặt dependencies:
dockerfile
USER node
- Sử dụng Multistage Builds: Giú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:
dockerfile
# Giai đoạn phát triển FROM node:20-alpine AS development WORKDIR /usr/src/app COPY package*.json ./ RUN npm ci COPY . . USER node # Giai đoạn xây dựng 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 # Giai đoạn sản xuất 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 bao gồm ba giai đoạn:
- Giai đoạn phát triển: Phục vụ cho việc phát triển cục bộ với tất cả các dependencies.
- Giai đoạn xây dựng: Xây dựng ứng dụng cho sản xuất.
- Giai đoạn sản xuất: Chạy phiên bản đã xây dựng cho 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:
bash
docker build -t nest-app .
Sau đó, chạy container đã được tối ưu hóa:
bash
docker run -p 3000:3000 nest-app
Kiểm tra kích thước của image mới bằng lệnh:
bash
docker images
Bạn sẽ nhận thấy kích thước image giảm đáng kể, giúp nó hiệu quả hơn trong môi trường sản xuất.
Khắc Phục Cá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ụngFROM node:20-alpine
thay vìFROM node:14-alpine
. - Lỗi:
nest command not found
: Nghĩa là Nest CLI chưa được cài đặt. Trong multistage build, hãy chắc chắn rằng bạn đã sao chép thư mụcnode_modules
từ giai đoạn phát triển, nơi mà 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, thì Dockerfile của bạn sẽ hơi khác một chút. Dưới đây là ví dụ:
dockerfile
# Giai đoạn phát triển
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
# Giai đoạn xây dựng
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
# Giai đoạn sản xuất
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
:
typescript
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à như vậy, bạn đã hoàn thành quá trình docker hóa ứng dụng NestJS của mình và tối ưu hóa cho môi trường production. Nếu bạn có ý định triển khai ứng dụng NestJS của mình, hãy tham khảo thêm tại sliplane.io.
source: viblo