Cách Deploy NodeJS Bằng Docker Trên VPS Từ A-Z Cho Người Mới

06/05/2026 · P T P · Chung

Cách deploy NodeJS bằng Docker trên VPS từ A-Z cho người mới bắt đầu

Deploy app NodeJS lên VPS thường là bước khiến người mới ngại nhất: sợ lỗi môi trường, sợ “chạy ở máy em nhưng lên server lại hỏng”, sợ cấu hình Nginx, PM2, port, firewall. Tin tốt: Docker giải quyết gần hết mớ rắc rối đó.

Thay vì cài Node, package, service trực tiếp lên VPS, bạn đóng gói app vào container. Kết quả: môi trường dev/staging/prod gần như giống nhau, dễ deploy, dễ rollback, dễ scale hơn. Với người mới, đây là con đường ngắn nhất để đưa app NodeJS lên mạng một cách gọn gàng, ít lỗi.

Trong bài này, bạn sẽ đi từ 0 đến chạy được app thực tế trên VPS: chuẩn bị server, viết Dockerfile, docker-compose.yml, build image, chạy container, map domain, reverse proxy bằng Nginx, bật HTTPS, debug lỗi cơ bản.


Vì sao nên deploy NodeJS bằng Docker?

Cách cũ thường là:

– SSH vào VPS
– Cài NodeJS
git clone
npm install
npm run build
– Chạy bằng PM2

Cách này vẫn ổn, nhưng có vài vấn đề:

Lệ thuộc môi trường server → lệch version Node, thiếu package hệ thống.
Khó lặp lại → server mới phải cài lại từ đầu.
Khó rollback → deploy lỗi thì xử lý thủ công.
Dễ “rác” server → nhiều app, nhiều version, khó quản lý.

Docker giúp:

App + môi trường → đóng gói cùng nhau.
Build một lần, chạy mọi nơi.
Tách biệt service → app này không ảnh hưởng app khác.
Triển khai chuẩn hóa → đặc biệt hữu ích khi làm team.


Bạn cần chuẩn bị gì?

Trước khi bắt đầu, hãy có:

1 VPS Linux: Ubuntu 22.04 là dễ nhất.
1 app NodeJS: ví dụ Express/NestJS/Next backend.
1 domain nếu muốn chạy thực tế có HTTPS.
– Kiến thức cơ bản:
– SSH vào server
– dùng terminal
– hiểu port là gì

Ví dụ app NodeJS chạy ở port 3000.


Bước 1: SSH vào VPS và cài Docker

Đầu tiên, đăng nhập VPS:

ssh root@your_vps_ip

Cập nhật hệ thống:

apt update && apt upgrade -y

Cài Docker:

curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

Kiểm tra:

docker --version

Cài Docker Compose plugin:

apt install docker-compose-plugin -y

Kiểm tra:

docker compose version

Nếu muốn chạy Docker không cần root, thêm user vào group docker:

usermod -aG docker $USER

Sau đó đăng xuất, đăng nhập lại.


Bước 2: Chuẩn bị app NodeJS cho production

Giả sử cấu trúc app như sau:

my-app/
├─ src/
├─ package.json
├─ package-lock.json
└─ server.js

Trong package.json, nên có script:

{
  "scripts": {
    "start": "node server.js"
  }
}

Nếu app dùng biến môi trường, tạo file .env:

PORT=3000
NODE_ENV=production

Lưu ý: không hard-code thông tin nhạy cảm như password DB, secret JWT vào code.


Bước 3: Viết Dockerfile

Tại thư mục gốc project, tạo file Dockerfile:

FROM node:20-alpine

WORKDIR /app

COPY package*.json ./ RUN npm ci --only=production

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

Giải thích nhanh:

FROM node:20-alpine → dùng image Node nhẹ.
WORKDIR /app → thư mục làm việc trong container.
COPY package*.json ./ → copy file package trước để tận dụng cache.
RUN npm ci --only=production → cài dependency production.
COPY . . → copy source code.
EXPOSE 3000 → app dùng port 3000.
CMD ["npm", "start"] → lệnh chạy app.

Nếu app cần build, ví dụ TypeScript/NestJS, nên dùng multi-stage build. Ví dụ:

FROM node:20-alpine AS builder

WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build

FROM node:20-alpine

WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY --from=builder /app/dist ./dist

EXPOSE 3000

CMD ["node", "dist/main.js"]

Cách này giúp image cuối nhẹ hơn.


Bước 4: Tạo .dockerignore

File này giúp tránh copy file thừa vào image:

node_modules
npm-debug.log
.git
.gitignore
.env
Dockerfile
docker-compose.yml

Kết quả: build nhanh hơn, image gọn hơn, tránh lộ dữ liệu không cần thiết.


Bước 5: Test Docker ngay trên máy local

Build image:

docker build -t my-node-app .

Chạy container:

docker run -d -p 3000:3000 --name my-node-app my-node-app

Kiểm tra:

docker ps

Xem log:

docker logs -f my-node-app

Nếu app mở được ở http://localhost:3000 thì Dockerfile ổn.

Dừng và xóa:

docker stop my-node-app
docker rm my-node-app

Bước 6: Dùng Docker Compose để quản lý dễ hơn

Tạo file docker-compose.yml:

version: "3.9"

services: app: build: . container_name: my-node-app ports: - "3000:3000" env_file: - .env restart: unless-stopped

Chạy:

docker compose up -d --build

Xem log:

docker compose logs -f

Dừng:

docker compose down

Vì sao nên dùng Compose?

– Lệnh ngắn hơn
– Dễ quản lý env, volume, network
– Sau này thêm Redis, MongoDB, PostgreSQL rất tiện


Bước 7: Đưa source code lên VPS

Có 2 cách phổ biến:

Cách 1: Git clone trực tiếp trên VPS

Cài Git nếu chưa có:

apt install git -y

Clone project:

git clone https://github.com/yourname/your-repo.git
cd your-repo

Cách 2: Upload code bằng SCP/SFTP

Ví dụ:

scp -r ./my-app root@your_vps_ip:/root/

Với người mới, Git clone thường tiện hơn.


Bước 8: Chạy app trên VPS bằng Docker Compose

Trong thư mục project trên VPS:

docker compose up -d --build

Kiểm tra container:

docker ps

Nếu VPS mở firewall, cho phép port app hoặc Nginx:

ufw allow 3000
ufw allow 80
ufw allow 443

Test nhanh:

curl http://localhost:3000

Nếu phản hồi OK → app đã chạy trên server.


Bước 9: Cấu hình Nginx làm reverse proxy

Không nên expose app Node trực tiếp cho production lâu dài. Tốt hơn: Nginx đứng trước, nhận request từ internet rồi chuyển vào container.

Cài Nginx:

apt install nginx -y

Tạo config:

nano /etc/nginx/sites-available/myapp

Nội dung:

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }

Kích hoạt:

ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

Trỏ domain về IP VPS tại DNS. Sau vài phút, truy cập domain sẽ vào app.


Bước 10: Bật HTTPS miễn phí với Let’s Encrypt

Cài Certbot:

apt install certbot python3-certbot-nginx -y

Cấp SSL:

certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot sẽ tự sửa config Nginx và bật HTTPS.

Kiểm tra gia hạn tự động:

systemctl status certbot.timer

Kết quả: app an toàn hơn, trình duyệt không báo “Not Secure”.


Bước 11: Quy trình deploy lại khi có code mới

Khi cập nhật app:

cd your-repo
git pull
docker compose up -d --build

Quy trình này nghĩa là:

– kéo code mới
– build lại image
– recreate container
– app chạy phiên bản mới

Nếu cần dọn image cũ:

docker image prune -a

Hãy cẩn thận vì lệnh này xóa image không dùng tới.


Lỗi phổ biến người mới hay gặp

Container chạy rồi nhưng web không vào được

Nguyên nhân thường là:

– app đang listen localhost thay vì 0.0.0.0
– map sai port
– firewall chặn
– Nginx proxy sai

Với Express, nên:

app.listen(3000, '0.0.0.0');

npm install lỗi khi build

Thường do:

– Node version không phù hợp
– package native cần build tools
– lock file cũ

Fix:

– đổi image Node phù hợp, ví dụ node:20-alpine
– kiểm tra package-lock.json
– nếu cần, dùng image Debian thay Alpine

App crash ngay sau khi start

Xem log:

docker compose logs -f

Thường do thiếu biến môi trường hoặc DB chưa kết nối được.


Kết luận

Với người mới, deploy NodeJS lên VPS bằng Docker là lựa chọn rất đáng học. Lợi ích lớn nhất không chỉ là “chạy được”, mà là chạy ổn định, dễ lặp lại, dễ sửa lỗi. Một khi đã có Dockerfiledocker-compose.yml, bạn có thể mang app đi gần như bất kỳ VPS nào mà quy trình vẫn giống nhau.

Lộ trình thực tế nên là:

– chạy local bằng Docker
– đưa lên VPS
– thêm Nginx
– thêm HTTPS
– sau đó mới nghĩ tới CI/CD, GitHub Actions, registry, zero-downtime deploy

Nếu bạn mới bắt đầu, đừng cố tối ưu quá sớm. Chỉ cần làm đúng 3 thứ: Docker hóa app, chạy ổn trên VPS, gắn domain + HTTPS. Chừng đó đã đủ để bạn có một hệ thống production cơ bản, sạch và chuyên nghiệp hơn rất nhiều so với deploy thủ công.

#bang #deploy #docker #nodejs #tren
Chia sẻ:
← Trước
Bộ Tiêu Chí Vàng Chọn Self-Hosted App Đáng Triển Khai Nhất

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

Bình luận

Chưa có bình luận. Hãy là người đầu tiên!