Viết Dockerfile đầu tiên cho ứng dụng Node.js từng bước

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Dockerfile là tờ hướng dẫn để Docker dựng image cho ứng dụng của bạn. Viết đúng thứ tự các dòng sẽ giúp build nhanh hơn và image gọn hơn. Hãy cùng đóng gói một ứng dụng Node.js đơn giản từ đầu.

Chuẩn bị ứng dụng mẫu

Giả sử bạn có thư mục dự án với package.json và file server.js như sau:

const http = require('http');
const port = process.env.PORT || 3000;

http.createServer((req, res) => {
  res.end('Xin chao tu container!');
}).listen(port, () => console.log('Dang chay o cong ' + port));

File package.json chỉ cần có tên, phiên bản và script start chạy node server.js.

Dockerfile cơ bản

Tạo file tên đúng là Dockerfile (không đuôi) ở thư mục gốc:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --omit=dev
COPY . .
EXPOSE 3000
CMD node server.js

Ý nghĩa từng dòng:

  • FROM: chọn image nền. Bản alpine nhỏ gọn hơn bản đầy đủ.
  • WORKDIR: thư mục làm việc trong container, tự tạo nếu chưa có.
  • COPY package*.json ./: chép riêng file khai báo thư viện trước.
  • RUN: chạy lệnh lúc build, ở đây là cài thư viện.
  • COPY . .: chép phần mã nguồn còn lại.
  • EXPOSE: ghi chú cổng ứng dụng lắng nghe. Nó không tự mở cổng ra ngoài.
  • CMD: lệnh chạy khi container khởi động.

Vì sao chép package.json trước?

Docker build theo từng lớp (layer) và lưu cache cho mỗi lớp. Nếu bạn chỉ sửa mã nguồn mà không đổi thư viện, các lớp trước COPY . . được dùng lại từ cache, nên bước npm install không phải chạy lại. Đảo thứ tự lại, mỗi lần sửa một dòng code là cài lại toàn bộ thư viện, rất tốn thời gian.

Thêm .dockerignore

Tạo file .dockerignore để không đưa thứ vô ích vào image:

node_modules
.git
.env
npm-debug.log
Dockerfile

Dòng .env đặc biệt quan trọng: bạn không muốn mật khẩu bị đóng gói vào image rồi vô tình đẩy lên registry công khai.

Build và chạy

docker build -t my-node-app:1.0 .
docker run -d -p 3000:3000 --name app my-node-app:1.0
docker logs app

Cờ -t đặt tên và tag cho image. Dấu chấm cuối lệnh build là ngữ cảnh build, tức thư mục hiện tại. Truy cập http://localhost:3000 để kiểm tra. Muốn truyền cấu hình, dùng -e PORT=4000 khi chạy.

Những lỗi người mới hay gặp

  1. Dùng tag latest cho image nền: build hôm nay và tuần sau có thể ra kết quả khác nhau. Hãy ghim phiên bản cụ thể như node:20-alpine.
  2. Chạy bằng quyền root: nên thêm USER node trước CMD vì image Node chính thức đã có sẵn người dùng này.
  3. Quên .dockerignore: image phình to và có thể lộ bí mật.
  4. Ứng dụng chỉ lắng nghe 127.0.0.1: trong container cần lắng nghe mọi địa chỉ (0.0.0.0) thì cổng mới truy cập được từ ngoài.

Kiểm tra image vừa tạo

Dùng docker images để xem dung lượng, và docker history my-node-app:1.0 để thấy từng lớp tốn bao nhiêu. Thói quen này giúp bạn phát hiện sớm lớp nào làm image phình ra.

Kết luận

Một Dockerfile tốt ngắn gọn, ghim phiên bản, tận dụng cache và không chứa bí mật. Bạn đã có đủ nền tảng để đóng gói bất kỳ ứng dụng web nhỏ nào. Bước tiếp theo là tìm hiểu multi-stage build để thu nhỏ image hơn nữa.

Nếu muốn có lộ trình rõ ràng cho cả Docker lẫn triển khai thực tế, hãy xem các khóa học tại codebem.com để luyện tay cùng bài tập.

author_photo
Nguyễn Đình Cường

0 comment