Tự động deploy NodeJS bằng Docker trên VPS với GitHub Actions: nhanh, sạch, ít lỗi
Deploy thủ công thường bắt đầu rất “ổn”: SSH vào VPS, git pull, npm install, restart app. Nhưng chỉ vài lần là lộ vấn đề: quên pull đúng branch, quên migrate, lệch môi trường, downtime lúc restart, “máy em chạy được”. Quy trình nhỏ → rủi ro lớn.
Giải pháp gọn, thực dụng: đóng gói app NodeJS bằng Docker, đẩy code lên GitHub, dùng GitHub Actions để tự động build và deploy lên VPS. Kết quả: mỗi lần push → pipeline chạy → VPS cập nhật đồng nhất, dễ rollback, dễ mở rộng.
Bài này đi theo hướng thực chiến: ít lý thuyết, tập trung thứ bạn cần để chạy được.
Vì sao nên kết hợp Docker + VPS + GitHub Actions?
Docker → môi trường đồng nhất
NodeJS rất hay dính lỗi kiểu:
– local Node 20, server Node 18
– local có package, server thiếu
– app phụ thuộc binary/native module khác OS
Docker giải quyết bằng cách đóng gói app + runtime + dependency thành image. Local chạy sao, server chạy gần như vậy.
VPS → rẻ, chủ động, đủ mạnh cho nhiều dự án
Với app vừa và nhỏ, VPS thường là lựa chọn cân bằng:
– rẻ hơn PaaS
– toàn quyền cài Nginx, Docker, firewall
– dễ host nhiều service trên cùng máy
Đổi lại: bạn phải tự lo deploy, bảo mật, backup. GitHub Actions giúp giảm mạnh phần “tay chân”.
GitHub Actions → CI/CD ngay trong repo
Không cần dựng Jenkins hay GitLab Runner riêng. Chỉ cần file workflow là có thể:
– chạy test
– build image
– SSH vào VPS
– pull code/image
– restart container
Push code → deploy tự động. Nhất quán, ít quên bước.
Kiến trúc triển khai đề xuất
Một flow phổ biến, dễ áp dụng:
1. Dev push code lên branch main
2. GitHub Actions được kích hoạt
3. Workflow SSH vào VPS
4. VPS pull code mới hoặc nhận lệnh cập nhật
5. Docker Compose rebuild/restart container
6. App NodeJS chạy phiên bản mới
Có 2 hướng chính:
– Hướng A: build ngay trên VPS
– đơn giản
– không cần registry
– hợp dự án nhỏ
– Hướng B: build image trên GitHub Actions, push lên registry rồi VPS pull
– sạch hơn
– deploy nhanh hơn
– hợp team/prod
Trong bài này, ưu tiên Hướng A vì dễ bắt đầu nhất.
Chuẩn bị trên VPS
Trên VPS Ubuntu, cài Docker và Docker Compose plugin:
Không “đẹp” bằng rollback theo image tag, nhưng đủ cứu production lúc gấp.
Lỗi thường gặp
Permission denied (publickey)
Nguyên nhân:
– sai private key trong GitHub Secret
– user SSH sai
– public key chưa nằm trong authorized_keys
Fix: test SSH từ local trước, rồi copy đúng private key vào secret.
docker: permission denied
User deploy chưa thuộc group docker.
Fix:
sudo usermod -aG docker $USER
Đăng nhập lại.
Container build được nhưng app crash
Thường do:
– thiếu biến môi trường
– npm start sai command
– app bind sai host/port
Với NodeJS, nên bảo đảm app listen trên 0.0.0.0, không phải chỉ localhost.
Ví dụ:
app.listen(process.env.PORT || 3000, '0.0.0.0');
git pull bị conflict trên VPS
Nguyên nhân: bạn sửa file trực tiếp trên server.
Fix: tránh sửa code trên VPS. Server chỉ nên là nơi chạy app. Config tách qua .env, Nginx, secret.
Kết luận
Nếu bạn muốn một quy trình deploy gọn, rẻ, dễ kiểm soát, bộ ba NodeJS + Docker + VPS + GitHub Actions là lựa chọn rất mạnh. Nó không quá phức tạp như Kubernetes, nhưng chuyên nghiệp hơn hẳn việc SSH tay mỗi lần release.
Công thức cốt lõi:
– Docker → đồng nhất môi trường
– VPS → chủ động hạ tầng
– GitHub Actions → tự động hóa deploy
– SSH + Compose → triển khai nhanh, dễ hiểu
Điểm quan trọng nhất không phải “xịn” đến đâu, mà là ổn định và lặp lại được. Một pipeline đơn giản, chạy chắc, luôn tốt hơn quy trình cầu kỳ nhưng khó bảo trì.
Nếu bạn mới bắt đầu, hãy triển khai phiên bản tối thiểu:
1. Dockerize app
2. Chạy ổn trên VPS bằng Compose
3. Tạo SSH key
4. Viết workflow GitHub Actions
5. Push một commit thử nghiệm
Chỉ cần vậy, bạn đã có CI/CD thực dụng cho dự án NodeJS. Từ đó, mới nâng cấp dần: test, healthcheck, rollback, registry, zero-downtime. Làm từng bước → ít lỗi, dễ vận hành, dễ ngủ ngon hơn sau mỗi lần deploy.