Xây dựng và Docker hóa ứng dụng Node.js với kiến trúc không trạng thái với sự trợ giúp từ Kinsta

theanh

Administrator
Nhân viên
Bài viết này nhận được sự hỗ trợ nhiệt tình của những người bạn thân mến của chúng tôi tại Kinsta, những người luôn cam kết mang đến trải nghiệm tốt nhất cho các nhà phát triển và doanh nghiệp, xây dựng để đạt hiệu suất và dễ sử dụng. Cảm ơn bạn!



Trong bài viết này, chúng ta sẽ thử tạo một ứng dụng Node.js không trạng thái và docker hóa ứng dụng đó, giúp môi trường phát triển của chúng ta sạch sẽ và hiệu quả. Trên đường đi, chúng ta sẽ khám phá những lợi ích của việc lưu trữ container trên các nền tảng như Kinsta, nền tảng này cung cấp môi trường lưu trữ được quản lý đồng thời hỗ trợ container Docker cũng như lưu trữ ứng dụng và cơ sở dữ liệu, cho phép người dùng triển khai và mở rộng quy mô ứng dụng của họ một cách linh hoạt và dễ dàng hơn.

Tạo ứng dụng Node.js​

Trong trường hợp bạn mới làm quen với mã, Node.js là nền tảng được xây dựng trên công cụ JavaScript của Chrome cho phép các nhà phát triển tạo ứng dụng phía máy chủ bằng JavaScript. Nền tảng này phổ biến vì tính chất nhẹ, hiệu suất hiệu quả và khả năng không đồng bộ.
Ứng dụng không trạng thái không lưu trữ bất kỳ thông tin nào về phiên của người dùng, cung cấp một cách sạch sẽ và hiệu quả để quản lý ứng dụng của bạn. Hãy cùng khám phá cách tạo ứng dụng Node.js theo cách này.

Bước 1: Khởi tạo dự án Node.js​

Đầu tiên, hãy tạo một thư mục mới và điều hướng đến thư mục đó:
Mã:
mkdir smashing-app && cd smashing-app
Tiếp theo, hãy khởi tạo một dự án Node.js mới:
Mã:
npm init -y

Bước 2: Cài đặt Express​

Express là một khuôn khổ ứng dụng web Node.js tối giản và linh hoạt, cung cấp một bộ tính năng mạnh mẽ cho các ứng dụng web và di động. Cài đặt Express bằng lệnh sau:
Mã:
npm install express

Bước 3: Tạo ứng dụng không trạng thái của bạn​

Tạo một tệp mới có tên là “app.js” và thêm mã sau:
Mã:
const express = require("express");const app = express();const port = process.env.PORT || 3000;app.get("/", (req, res) => { res.send("Chào mừng đến với ứng dụng Node.js không trạng thái tuyệt vời của chúng tôi!");});app.listen(port, () => { console.log(`Ứng dụng đang lắng nghe tại http://localhost:${port}`);});
Chúng ta hãy cùng khám phá điều này một chút. Sau đây là những gì mỗi dòng thực hiện:
  • const express = require("express");
    Dòng này nhập khung Express.js vào mã, giúp sử dụng được.
  • const app = express();
    Dòng này tạo một phiên bản của khung Express.js có tên là app. Phiên bản app này là nơi chúng ta định nghĩa các tuyến máy chủ và cấu hình của mình.
  • const port = process.env.PORT || 3000;
    Dòng này đặt số cổng cho máy chủ. Nó tìm kiếm số cổng được đặt trong biến môi trường có tên là PORT. Nếu biến đó không được đặt, nó sẽ mặc định là cổng 3000.
  • app.get("/", (req, res) => {}
    Dòng này định nghĩa một tuyến đường cho máy chủ khi yêu cầu GET được thực hiện tới URL gốc (“/”).
  • res.send("Welcome to our smashing stateless Node.js app!");
    Dòng này gửi chuỗi “Welcome to our smashing stateless Node.js app!” dưới dạng phản hồi cho yêu cầu GET được thực hiện tới URL gốc.
  • app.listen(port, () => {})
    Dòng này khởi động máy chủ và lắng nghe trên số cổng được chỉ định trước đó.
Bây giờ, hãy chạy ứng dụng bằng:
Mã:
node app.js
Ứng dụng Node.js của bạn hiện đang chạy ở http://localhost:3000.

Kiến trúc không trạng thái​

Kiến trúc không trạng thái có nghĩa là máy chủ không lưu trữ bất kỳ thông tin nào về phiên của người dùng, mang lại một số lợi ích:
  • Khả năng mở rộng
    Các ứng dụng không trạng thái có thể dễ dàng mở rộng theo chiều ngang bằng cách thêm nhiều phiên bản hơn mà không phải lo lắng về dữ liệu phiên.
  • Đơn giản
    Không cần quản lý dữ liệu phiên, logic ứng dụng trở nên đơn giản hơn và dễ bảo trì hơn.
  • Khả năng chịu lỗi
    Các ứng dụng không trạng thái có thể phục hồi nhanh chóng sau các lỗi vì không có trạng thái phiên nào bị mất hoặc phục hồi.
Được rồi, chúng ta đã có máy chủ Node.js chạy cục bộ, nhưng làm sao chúng ta có thể đóng gói nó để bất kỳ ai cũng có thể chạy được? Ngay cả những người không cài đặt Node.js và chạy trên bất kỳ nền tảng nào? Đó chính là lúc Docker xuất hiện.

Dockerizing The App​

Docker là một công cụ giúp các nhà phát triển xây dựng, vận chuyển và chạy các ứng dụng trong môi trường chứa. Công cụ này giúp đơn giản hóa quá trình triển khai các ứng dụng trên nhiều nền tảng và môi trường khác nhau.

Bước 1: Cài đặt Docker​

Trước tiên, hãy đảm bảo rằng bạn đã cài đặt Docker trên máy của mình. Bạn có thể tải xuống tại đây.

Bước 2: Tạo Dockerfile​

Tạo một tệp mới có tên Dockerfile trong thư mục dự án của bạn và thêm mã sau:
Mã:
FROM node:18-alpineWORKDIR /usr/src/appCOPY package*.json ./RUN npm installCOPY . .ENV PORT=3000CMD [ "node", "app.js" ]
Một lần nữa, chúng ta hãy xem xét chi tiết hơn về tác dụng của lệnh này:
  • FROM node:18-alpine
    Dòng này chỉ định hình ảnh cơ sở cho hình ảnh Docker này. Trong trường hợp này, đó là hình ảnh Docker Node.js chính thức dựa trên bản phân phối Alpine Linux. Điều này cung cấp Node.js cho vùng chứa Docker, giống như một "máy ảo" nhưng nhẹ hơn và hiệu quả hơn.
  • WORKDIR /usr/src/app
    Dòng này đặt thư mục làm việc bên trong vùng chứa Docker thành /usr/src/app.
  • COPY . .
    Dòng này sao chép tất cả các tệp từ thư mục cục bộ sang thư mục làm việc trong vùng chứa Docker.
  • RUN npm install
    Dòng này cài đặt các phụ thuộc được chỉ định trong tệp package.json.
  • ENV PORT=3000
    Sử dụng chỉ thị này, chúng ta làm cho ứng dụng có thể cấu hình được nhiều hơn bằng cách sử dụng biến môi trường PORT. Phương pháp này mang lại sự linh hoạt và cho phép các nhà cung cấp dịch vụ lưu trữ như Kinsta kết nối ứng dụng với cơ sở hạ tầng của họ một cách liền mạch.
  • CMD [ "node", "app.js" ]
    Dòng này chỉ định lệnh sẽ chạy khi vùng chứa Docker khởi động. Trong trường hợp này, nó chạy lệnh node với app.js làm đối số, lệnh này sẽ khởi động ứng dụng Node.js.
Do đó, Dockerfile này sẽ xây dựng một hình ảnh Docker thiết lập thư mục làm việc, cài đặt các phụ thuộc, sao chép tất cả các tệp vào vùng chứa, hiển thị cổng 3000 và chạy ứng dụng Node.js bằng lệnh node.

Bước 3: Xây dựng và chạy vùng chứa Docker​

Bây giờ chúng ta hãy xây dựng và chạy cục bộ để đảm bảo mọi thứ hoạt động tốt.
Mã:
docker build -t smashing-app
Khi thành công, chúng ta sẽ chạy vùng chứa:
Mã:
docker run -p 3000:3000 smashing-app
Chúng ta hãy chia nhỏ điều này vì -p 3000:3000 có vẻ khó hiểu. Sau đây là những gì đang xảy ra:
  1. docker run là lệnh được dùng để chạy một vùng chứa Docker.
  2. -p 3000:3000 là tùy chọn ánh xạ cổng 3000 trong vùng chứa Docker tới cổng 3000 trên máy chủ. Điều này có nghĩa là cổng 3000 của vùng chứa sẽ có thể truy cập được từ máy chủ tại cổng 3000. Số cổng đầu tiên là số cổng của máy chủ (của chúng tôi) và số cổng thứ hai là số cổng của container.
  3. Chúng ta có thể ánh xạ cổng 1234 trên máy của mình tới cổng 3000 trên container, sau đó localhost:1234 sẽ trỏ tới container:3000 và chúng ta vẫn có thể truy cập vào ứng dụng.
  4. smashing-app là tên của hình ảnh Docker mà container dựa trên, hình ảnh mà chúng ta vừa xây dựng.
Ứng dụng Node.js Dockerized của bạn hiện sẽ chạy tại [URL=http://localhost?utm_source=diendancongnghe.com]http://localhost:3000[/URL].

Khi chạy container Docker, chúng ta cũng có thể truyền thêm giá trị PORT tùy chỉnh dưới dạng biến môi trường:
Mã:
docker run -p 8080:5713 -d -e PORT=5713 smashing-app
Lệnh này ánh xạ cổng 5713 của vùng chứa tới cổng 8080 của máy chủ và đặt biến môi trường PORT thành 5713 bên trong vùng chứa.

Sử dụng biến môi trường PORT trong Dockerfile cho phép linh hoạt và thích ứng hơn khi triển khai ứng dụng Node.js tới nhiều nhà cung cấp dịch vụ lưu trữ khác nhau, bao gồm Kinsta.

Nhiều lợi thế Smashing hơn của việc Docker hóa ứng dụng Node.js​

Docker hóa ứng dụng Node.js mang lại một số lợi thế cho các nhà phát triển và toàn bộ vòng đời ứng dụng. Sau đây là một số lợi ích chính bổ sung với các ví dụ mã:

Quản lý phụ thuộc đơn giản​

Docker cho phép bạn đóng gói tất cả các phụ thuộc trong chính container, giúp quản lý và chia sẻ dễ dàng hơn giữa các thành viên trong nhóm. Ví dụ: giả sử bạn có tệp package.json với phiên bản cụ thể của một gói:
Mã:
{ "dependencies": { "lodash": "4.17.21" }}
Bằng cách đưa điều này vào Dockerfile của bạn, phiên bản cụ thể của lodash sẽ tự động được cài đặt và đóng gói trong container của bạn, đảm bảo hành vi nhất quán trên các môi trường.
Quản lý phiên bản ứng dụng dễ dàng​
Docker cho phép bạn gắn thẻ và tạo phiên bản cho hình ảnh ứng dụng của mình, giúp bạn dễ dàng quay lại các phiên bản trước đó hoặc triển khai các phiên bản khác nhau song song. Ví dụ, nếu bạn muốn xây dựng phiên bản mới cho ứng dụng của mình, bạn có thể gắn thẻ bằng lệnh sau:
Mã:
docker build -t smashing-app:v2 .
Sau đó, bạn có thể chạy nhiều phiên bản ứng dụng của mình cùng lúc:
Mã:
docker run -p 3000:3000 -d smashing-app:v1docker run -p 3001:3000 -d smashing-app:v2
Biến môi trường​
Docker giúp bạn dễ dàng quản lý các biến môi trường, có thể truyền vào ứng dụng Node.js của bạn để sửa đổi hành vi của ứng dụng dựa trên môi trường (phát triển, dàn dựng, sản xuất). Ví dụ, trong tệp app.js của bạn:
Mã:
const express = require('express');const app = express();const port = process.env.PORT || 3000;const env = process.env.NODE_ENV || 'development';app.get('/', (req, res) => { res.send(`Chào mừng đến với ứng dụng Node.js không trạng thái tuyệt vời của chúng tôi đang chạy ở chế độ ${env}!`);});app.listen(port, () => { console.log(`Ứng dụng tuyệt vời đang lắng nghe tại http://localhost:${port}`);});
Trong Dockerfile của bạn, bạn có thể đặt biến NODE_ENV:
Mã:
FROM node:18-alpineWORKDIR /usr/src/appCOPY package*.json ./RUN npm installCOPY . .ENV NODE_ENV=productionCMD [ "node", "app.js" ]
Hoặc bạn có thể truyền nó khi chạy container:
Mã:
docker run -p 3000:3000 -d -e NODE_ENV=production smashing-app
Tóm tắt của điều này là thông qua Dockerizing các ứng dụng node, chúng ta có thể loại bỏ toàn bộ lớp vấn đề "hoạt động trên máy của tôi" đồng thời tăng khả năng tái sử dụng, khả năng kiểm tra và khả năng di động của các ứng dụng Node.js của chúng ta. 🎉

Lưu trữ các container bằng Kinsta​

Bây giờ chúng ta đã có ứng dụng Node.js không trạng thái được Dockerized, bạn có thể tự hỏi nên lưu trữ nó ở đâu. Kinsta được biết đến rộng rãi nhờ dịch vụ lưu trữ ứng dụng và cơ sở dữ liệu. Hãy cùng khám phá cách chúng ta thực hiện việc này với Kinsta theo từng bước.
  1. Đăng nhập hoặc đăng ký vào tài khoản Kinsta của bạn.
  2. Từ đó, bạn sẽ vào được bảng điều khiển của mình.
  3. Sử dụng thanh bên, điều hướng đến Ứng dụng.


  4. Từ đây, bạn sẽ có thể Thêm Dịch vụ loại ứng dụng.
  5. Sau khi thêm ứng dụng, bạn sẽ được mời kết nối tài khoản GitHub của mình với Kinsta để Kinsta có thể tự động triển khai ứng dụng của bạn khi có bản cập nhật được đẩy lên đó.
  6. Bây giờ, bạn có thể chọn kho lưu trữ chứa mã bạn muốn triển khai, cùng với việc thiết lập một số thông tin chi tiết cơ bản như tên ứng dụng và các biến môi trường.


  7. Tiếp theo, chúng ta chỉ định môi trường xây dựng ứng dụng của mình. Tại đây, chúng ta chỉ định vị trí của Dockerfile trong kho lưu trữ mà chúng ta vừa tạo.
  8. Cuối cùng, chúng ta phân bổ tài nguyên máy tính cho vùng chứa của mình, nhập thông tin thanh toán và chúng ta đã sẵn sàng!
Kinsta hiện sẽ xây dựng và triển khai ứng dụng của chúng ta và cung cấp cho chúng ta một liên kết công khai, an toàn để có thể truy cập. Ứng dụng của chúng ta hiện đã được xuất bản lên web!

Kết luận​

Trong hướng dẫn này, chúng tôi đã xây dựng một ứng dụng Node.js và Dockerized nó, giúp dễ dàng triển khai trên nhiều môi trường khác nhau. Chúng tôi cũng đã khám phá những lợi ích của kiến trúc không trạng thái và đề cập đến một số lựa chọn tuyệt vời để lưu trữ container, như Kinsta.
 
Back
Bên trên