DEV Community

lam duc
lam duc

Posted on

Hướng dẫn triển khai Docker cho ứng dụng Node.js (Cho người mới bắt đầu)

Docker đã trở thành một công cụ không thể thiếu giúp chuẩn hóa môi trường phát triển và triển khai ứng dụng. Đối với các lập trình viên Node.js, việc đưa ứng dụng vào container giúp tránh được lỗi "chạy được trên máy tôi nhưng lỗi trên server".

Trong bài viết này, chúng ta sẽ từng bước xây dựng một Dockerfile cơ bản, build image, chạy container và cấu hình các biến môi trường một cách an toàn.


1. Chuẩn bị ứng dụng Node.js đơn giản

Giả sử bạn có một ứng dụng Node.js cơ bản sử dụng Express.

File package.json:

{
  "name": "node-docker-demo",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}
Enter fullscreen mode Exit fullscreen mode

File index.js:

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.send(`Hello World từ Docker! Môi trường: ${process.env.NODE_ENV || 'development'}`);
});

app.listen(PORT, () => {
  console.log(`Ứng dụng đang chạy trên cổng ${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

2. Tạo file .dockerignore

Trước khi viết Dockerfile, bạn cần tạo một file .dockerignore ở thư mục gốc của dự án. File này ngăn không cho các thư mục không cần thiết (như node_modules hoặc file log) bị copy vào trong Docker image, giúp giảm dung lượng image và tăng tốc độ build.

node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
Enter fullscreen mode Exit fullscreen mode

3. Viết Dockerfile cơ bản

Tạo một file tên là Dockerfile (không có phần mở rộng) tại thư mục gốc của dự án:

# Bước 1: Chọn base image chính thức của Node.js (sử dụng phiên bản LTS và bản rút gọn alpine để tối ưu dung lượng)
FROM node:18-alpine

# Bước 2: Thiết lập thư mục làm việc bên trong container
WORKDIR /usr/src/app

# Bước 3: Sao chép package.json và package-lock.json (nếu có) trước
# Điều này giúp tận dụng Docker layer cache khi không có thay đổi về dependency
COPY package*.json ./

# Bước 4: Cài đặt các dependencies
RUN npm install --only=production

# Bước 5: Sao chép toàn bộ mã nguồn vào container
COPY . .

# Bước 6: Khai báo port mà container sẽ lắng nghe khi chạy
EXPOSE 3000

# Bước 7: Lệnh để khởi chạy ứng dụng
CMD [ "npm", "start" ]
Enter fullscreen mode Exit fullscreen mode

4. Build Docker Image

Mở terminal tại thư mục chứa Dockerfile và chạy lệnh sau để build image:

docker build -t node-docker-demo:1.0 .
Enter fullscreen mode Exit fullscreen mode

Trong đó:

  • -t node-docker-demo:1.0: Đặt tên (tag) cho image là node-docker-demo với phiên bản 1.0.
  • .: Chỉ định ngữ cảnh build (build context) là thư mục hiện tại.

5. Chạy Docker Container và Truyền Biến Môi Trường

Sau khi build thành công, bạn có thể khởi chạy container từ image vừa tạo:

docker run -d -p 8080:3000 --name my-node-app -e NODE_ENV=production node-docker-demo:1.0
Enter fullscreen mode Exit fullscreen mode

Giải thích các tham số:

  • -d: Chạy container dưới nền (detached mode).
  • -p 8080:3000: Ánh xạ cổng 8080 của máy host vào cổng 3000 bên trong container.
  • --name my-node-app: Đặt tên cho container đang chạy để dễ quản lý.
  • -e NODE_ENV=production: Truyền biến môi trường vào ứng dụng.
  • node-docker-demo:1.0: Tên image và tag đã build ở bước trước.

Bây giờ, bạn có thể truy cập http://localhost:8080 trên trình duyệt để kiểm tra kết quả.


6. Các lưu ý quan trọng về bảo mật và tối ưu hóa

Khi triển khai thực tế, lập trình viên cần lưu ý các điểm sau để đảm bảo an toàn cho ứng dụng:

  1. Không chạy container bằng quyền root: Mặc định, các container Node.js chạy với quyền root. Điều này tiềm ẩn rủi ro bảo mật lớn. Image Node.js chính thức đã có sẵn một user bảo mật tên là node. Hãy chuyển sang user này trước khi khởi chạy ứng dụng bằng cách thêm dòng sau vào trước lệnh CMD:
   USER node
Enter fullscreen mode Exit fullscreen mode
  1. Sử dụng phiên bản Node.js cụ thể:
    Tránh sử dụng tag latest (ví dụ: FROM node). Hãy luôn chỉ định rõ phiên bản ổn định (như node:18-alpine hoặc node:20-slim) để đảm bảo tính nhất quán trên mọi môi trường.

  2. Quản lý biến môi trường nhạy cảm:
    Không bao giờ lưu các thông tin nhạy cảm như API key, mật khẩu cơ sở dữ liệu trực tiếp trong Dockerfile. Hãy truyền chúng qua tham số -e khi chạy container, hoặc sử dụng các file .env để bảo mật thông tin tốt hơn.

Top comments (0)