Deploy NodeJS bằng Docker Compose trên VPS: hướng dẫn thực chiến từng bước
Deploy app NodeJS lên VPS nghe đơn giản: build app, chạy process, mở port. Thực tế hơn nhiều: env, network, persist data, restart policy, reverse proxy, SSL, log, zero-downtime tương đối. Làm thiếu 1 mắt xích → app chạy local ngon, lên server lỗi ngay.
Bài này đi theo hướng thực chiến: từ một app NodeJS bất kỳ, đóng gói bằng Docker, orchestration bằng Docker Compose, đưa lên VPS, chạy sau Nginx reverse proxy. Mục tiêu: dễ lặp lại, dễ bảo trì, ít lỗi môi trường.
Vì sao nên dùng Docker Compose trên VPS?
Nếu deploy NodeJS “thủ công”, flow thường là:
– cài Node
– pull code
– npm install
– chạy pm2 hoặc node server.js
– cấu hình Nginx riêng
– cập nhật bản mới → dễ lệch môi trường
Docker Compose giải quyết khá gọn:
– Đồng nhất môi trường → local/server giống nhau
– Tách service rõ ràng → app, db, redis, nginx
– Khởi động lại dễ → docker compose up -d
– Rollback dễ hơn → quay lại image/cấu hình cũ
– Onboarding nhanh → dev khác chỉ cần Docker
Compose đặc biệt hợp cho:
– app nhỏ-vừa
– 1 VPS
– chưa cần Kubernetes
– muốn quy trình triển khai rõ, ít overhead
Kiến trúc triển khai đề xuất
Một mô hình phổ biến:
– NodeJS app → chạy trong container
– Nginx → reverse proxy, nhận request từ internet
– Docker network → app/nginx nói chuyện nội bộ
– VPS → Ubuntu 22.04 hoặc tương đương
– Domain → trỏ về IP VPS
– SSL → cấu hình sau khi app chạy ổn
– restart: always → VPS reboot, container tự lên
– expose thay vì ports cho app → app không public trực tiếp
– Nginx mới là service public cổng 80
– 2 container chung app_network → gọi nhau qua service name
Bước 5: Cấu hình Nginx reverse proxy
Tạo file nginx/default.conf:
server {
listen 80;
server_name your-domain.com www.your-domain.com;
Với mô hình đơn giản, có thể cài Certbot ngay trên VPS host rồi mount cert vào Nginx. Tuy nhiên cách này cần thêm cấu hình. Nếu muốn tối giản hơn, nhiều team chọn Caddy hoặc Traefik vì tự cấp SSL.
Nếu vẫn dùng Nginx thuần, sau khi có cert, config sẽ có:
– server 80 → redirect 443
– server 443 → dùng ssl_certificate, ssl_certificate_key
Điểm mấu chốt: đừng xem SSL là bước “để sau rất lâu”. App public không có HTTPS → kém an toàn, browser cảnh báo.
Bước 9: Cập nhật phiên bản mới
Khi có code mới:
git pull
docker compose up -d --build
Flow này đủ cho đa số app nhỏ-vừa.
Nếu muốn dọn image cũ:
docker image prune -a
Cảnh báo bảo mật và dữ liệu: lệnh trên sẽ xóa image không còn được container sử dụng. Nếu bạn đang giữ image cũ để rollback, đừng chạy vội.
Nếu cần restart nhanh:
docker compose restart
Nếu muốn dừng toàn bộ:
docker compose down
Các lỗi thực tế rất hay gặp
App chạy local, lên VPS lỗi 502
Thường do:
– app không listen 0.0.0.0
– sai port
– container app crash
– Nginx proxy nhầm host/port
Check:
docker compose logs app
docker compose logs nginx
Env không load
Nguyên nhân:
– file .env thiếu biến
– sai tên biến
– app đọc env trước khi config đúng
Fix:
– kiểm tra env_file
– log thử process.env.PORT
Build chậm, image nặng
Nguyên nhân:
– copy cả node_modules
– không có .dockerignore
– dùng image base quá lớn
Nếu có DB trong container mà không mount volume → down/recreate dễ mất data.
Fix:
– dùng named volume
– hoặc tách DB sang managed service
Một số mẹo production đáng giá
– Dùng healthcheck → Compose biết container còn khỏe không
– Giới hạn log → tránh đầy disk
– Backup định kỳ → nhất là DB, uploads
– Không chạy app bằng root nếu có thể
– Tách .env production khỏi code repo
– Dùng tag image cố định thay vì latest trong môi trường quan trọng
– Giám sát CPU/RAM/disk → VPS nhỏ rất dễ đầy ổ vì log/image
Compose không phải “chuẩn cuối cùng”, nhưng với 1 VPS, nó là điểm cân bằng rất tốt giữa đơn giản và đủ chuyên nghiệp.
Kết luận
Deploy NodeJS bằng Docker Compose trên VPS là một lựa chọn cực thực dụng: nhanh setup, dễ lặp lại, ít lệch môi trường, phù hợp production quy mô nhỏ-vừa. Quy trình cốt lõi chỉ gồm vài khối:
– đóng gói app bằng Dockerfile
– ghép service bằng docker-compose.yml
– đặt Nginx làm reverse proxy
– trỏ domain, thêm SSL
– dùng log + restart policy để vận hành ổn định
Điều quan trọng nhất không phải “chạy được”, mà là chạy ổn định sau nhiều lần cập nhật. Khi bạn có thể git pull → docker compose up -d --build và hệ thống vẫn lên mượt, lúc đó quy trình deploy mới thật sự trưởng thành.
Nếu mới bắt đầu, hãy triển khai trước với 1 app NodeJS + 1 Nginx container. Khi quen rồi, bạn có thể mở rộng thêm PostgreSQL, Redis, CI/CD, auto SSL, monitoring. Đi từng bước như vậy → ít lỗi, dễ kiểm soát, sát thực tế hơn nhiều.