- vừa được xem lúc

[Nodejs thực chiến] Dockerize, Containerize nodejs app thật chuẩn

0 0 33

Người đăng: Nguyễn Kỳ Thịnh

Theo Viblo Asia

1. Đặt vấn đề:

  • Container là một phương pháp đóng gói ứng dụng để ứng dụng có thể chạy với các phụ thuộc của mình (gồm source code và library, runtime, framework…) một cách độc lập, tách biệt với các chương trình khác.
  • Tool đầu tiên, phổ biến nhất để container ứng dụng là Docker. Ngoài ra còn nhiều nhiều tools khác.
  • Có rất nhiều blog hướng dẫn containerize nodejs nhưng mình thấy rằng khá sơ khai. Với blog này hy vọng giúp mọi ngừoi containerize nodejs app một cách chuẩn hơn.

2. Bước đầu tiên

  • Source code ví dụ mình fork của freecodecamp về repo của mình. source.
  • Để containerize mình tạo file Dockerfile:
#1 Từ base image
FROM node
WORKDIR /app #2 Coppy toàn bộ source
COPY . . #3 install dependence
RUN npm i # build code
RUN npm run build # run app
CMD [ "npm", "run", "start" ]
  • Run build docker bằng docker-compose: docker compose up --build
  • Check health: curl http://localhost:3333/users Server trả về: {"id":0,"name":"Test containerize"}
  • Check size image: docker image inspect node-containerize_server --format='{{.Size}}', Kết quả: 1755772592 = 1,76G
  • Các bước tiếp theo mình sẽ thực hiện để giảm image zize và tăng tính hợp lý cho dockerfile.

3. Tạo dockerignore file

  • File dockerignore sẽ giúp docker
  1. bỏ qua mọt số file không cần thiết cho quá trình build image.
  2. Đảm bảo môi trường container không có liên hệ với các config, các dependence của môi trường local. Ví dụ môi trường local dùng node:14, docker dùng node:16, nếu coppy folder node_modules từ môi trường sẽ có thể dẫn đến bug.
  • touch .dockerignore
# Ignore file IDE setting
.vscode/
# Ignore folder node_modules
node_modules/ # Ignore file build
dist/ # Ignore các file folder khác không cần sửa dung
npm-debug.log
test/
  • Image size không thay đổi nhiều. > 1,7G
  • Thời gian build tăng lên do không còn node_modules nên npm i lâu hơn

4. Chọn base image:

  • Ban đầu: FROM node

  • Thành: FROM node:18.13.0-alpine3.16@sha256:3eb81689b639f6a7308c04003653daa94122bfcdbba9945e897b12cfe10bb034 as node

  • Giải thích:

    • node -> imgae có node
    • 18.13.0 version của node, nên chọn các version chẳn 14, 16 18 là các version LTS
    • alpine một hệ điều hành nân linux nhẹ hơn ubuntu
    • Phần @sha256:3....DIGEST Là định danh độc lập và bất biến của image
  • Kết quả khi build image size: 978871571 = 98M = 0.97G Bé hơn nhiều so với 1,72G. Chủ yếu là do alpine có size nhỏ hơn.

  • Thời gian build nhỏ hơn một tý do thừoi gian tải image nhanh hơn.

5. Install dependences.

  • Ban đầu
RUN npm i
RUN npm run build
RUN ["npm", "run", "start"]
  • Thành
RUN npm ci
RUN npm run build
RUN npm prune --production
RUN ["node", "dist/main"]
  • Giải thích:

    • npm ci chỉ install từ file package-log.json
    • npm prune --production remove devDependences vốn không cần thiết khi chạy trên production
    • npm run start bản chất là nest start chạy file source chưa build đổi thành node dist/main chạy file code đã build
  • Kết quả image size: 931057119 = 93M bé hơn một chút so với 98M. Nhưng thực tế khi mình làm việc thì source dự án thường lớn hơn source đang dùng để test nhiều lần nên với cánh này size sẽ bé hơn khá nhiều.

5. Multi stage

  • Thêm:
FROM node as server ENV NODE_ENV=production WORKDIR /app # COPY --from=server-builder /app/ /app/
COPY --from=server-builder /app/node_modules /app/node_modules
COPY --from=server-builder /app/.env /app/
COPY --from=server-builder /app/dist /app/dist
  • COPY --from=server-builder /app/.env /app/ Nếu config thông qua configMap hay secretKeys thì không cần coppy file này.
  • Kết quả size giảm còn 414639502 = 41M Chưa bằng 1/2 của 93M.
  • Nguyên nhân do khi install và build tạo rất nhiều file cache, file log. Tạo image mới chỉ coppy những folder cần thiết giúp giảm size file đi rất nhiều.
  • Xem thêm tại document của docker Mutil stage

6. Kết luận:

  • Image size giảm từ 1,7G -> 0.41G, ứng dụng vẫn chạy bình thường.
  • Dockerfile:
#1 Từ base image
FROM node:18.13.0-alpine3.16@sha256:3eb81689b639f6a7308c04003653daa94122bfcdbba9945e897b12cfe10bb034 as node
FROM node as server-builder
WORKDIR /app #2 Coppy toàn bộ source
COPY . . #3 install dependence
RUN npm ci #4 build code
RUN npm run build #4 remove dev dependence
RUN npm prune --production #5 Coppy qua image mới
FROM node as server ENV NODE_ENV=production WORKDIR /app COPY --from=server-builder /app/node_modules /app/node_modules
COPY --from=server-builder /app/.env /app/
COPY --from=server-builder /app/dist /app/dist
#6 run app
CMD [ "node", "dist/main.js" ] 
  • Full source/ branch final here

  • Mọi người có thể xem thêm các bài viết của mình trong seri Node thực chiến

  • Cảm ơn mọi người đã đọc.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 373

- vừa được xem lúc

Phần 1: Giới thiệu về Kubernetes

Kubernetes là gì. Trang chủ: https://kubernetes.io/. Ai cần Kubernetes.

0 0 80

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 1- Lịch sử)

1. Vì sao nên sử dụng. . .

0 0 85

- vừa được xem lúc

Docker - những kiến thức cơ bản phần 1

Giới thiệu. Nếu bạn đang làm ở một công ty công nghệ thông tin, chắc rằng bạn đã được nghe nói về Docker.

0 0 65

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 2 - Dockerfile)

1. Mở đầu.

0 0 53

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 3: Docker-compose)

1. Mở đầu. . .

0 0 105