DevOps Workflow Trên VPS 2026: Git, Docker, CI/CD Tự Động Deploy Cho Solo Dev & Team Nhỏ
Push code lên GitHub → 2 phút sau code tự động deploy lên VPS. Không cần SSH, không cần copy file, không sợ quên bước. Đó là DevOps workflow — và bài này sẽ hướng dẫn bạn setup từ A-Z trên VPS giá rẻ.
❌ Không DevOps
- SSH vào VPS mỗi lần update
- Copy file thủ công
- Quên restart service → web chết
- Không rollback được
- Deploy 2h sáng vì sợ user thấy lỗi
✅ Có DevOps
git push→ tự deploy- Test tự động trước khi deploy
- Restart service tự động
- Rollback 1 lệnh
- Deploy lúc nào cũng được, zero downtime
📋 Mục Lục
Các Khái Niệm DevOps Cơ Bản
| Khái niệm | Ý nghĩa | Ví dụ |
|---|---|---|
| CI (Continuous Integration) | Tự động test code mỗi khi push | GitHub Actions chạy npm test mỗi PR |
| CD (Continuous Delivery) | Tự động deploy code đã test lên server | Push main → build Docker → deploy VPS |
| Container | Đóng gói app + dependencies vào 1 unit | Docker container chạy Node.js + node_modules |
| Pipeline | Chuỗi các bước CI/CD tự động | Test → Build → Push Image → Deploy |
| Zero-Downtime | Deploy không làm gián đoạn service | Start container mới → switch traffic → kill cũ |
Setup VPS Ban Đầu
VPS cần cài Docker + Docker Compose. Chạy 3 dòng:
# Cài Docker
curl -fsSL https://get.docker.com | sudo bash
sudo usermod -aG docker $USER
# Cài Docker Compose
sudo apt install -y docker-compose-plugin
# Verify
docker --version # Docker version 27.x
docker compose version # Docker Compose v2.x
Docker Hóa Ứng Dụng
Ví dụ ứng dụng Node.js + Express. Tạo Dockerfile:
# Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Tối ưu build với multi-stage:
# Dockerfile (multi-stage - nhẹ hơn 60%)
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
EXPOSE 3000
CMD ["node", "dist/server.js"]
Docker Compose Cho Multi-Service
App thực tế thường có nhiều service: web + database + redis + nginx. docker-compose.yml:
version: '3.8'
services:
app:
build: .
container_name: myapp
restart: always
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgres://user:pass@db:5432/mydb
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
db:
image: postgres:16-alpine
container_name: myapp_db
restart: always
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
interval: 10s
retries: 5
redis:
image: redis:7-alpine
container_name: myapp_redis
restart: always
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
retries: 5
nginx:
image: nginx:alpine
container_name: myapp_nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- app
volumes:
pgdata:
redis_data:
Deploy 1 lệnh:
docker compose up -d --build
GitHub Actions CI/CD Pipeline
Tạo file .github/workflows/deploy.yml trong repo:
name: Deploy to VPS
on:
push:
branches: [main]
workflow_dispatch: # Cho phép deploy thủ công
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
- run: npm ci
- run: npm test
- run: npm run lint
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
script: |
cd /opt/myapp
git pull origin main
docker compose up -d --build
docker system prune -f
- name: Health Check
run: |
sleep 10
curl -f https://yourdomain.com/health || exit 1
- name: Notify Telegram
if: always()
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
message: |
🚀 Deploy ${{ job.status }}
Repo: ${{ github.repository }}
Branch: ${{ github.ref_name }}
Commit: ${{ github.sha }}
Setup GitHub Secrets
Vào Repo → Settings → Secrets and variables → Actions, thêm:
| Secret | Giá trị |
|---|---|
| VPS_HOST | IP VPS của bạn |
| VPS_USER | deploy (tạo user riêng, KHÔNG dùng root) |
| VPS_SSH_KEY | Private SSH key của user deploy |
| TELEGRAM_BOT_TOKEN | Token bot Telegram |
| TELEGRAM_CHAT_ID | Chat ID nhận thông báo |
Tạo User Deploy Trên VPS (Security Best Practice)
# Trên VPS - tạo user deploy riêng
sudo useradd -m -s /bin/bash deploy
sudo usermod -aG docker deploy
sudo mkdir -p /opt/myapp
sudo chown -R deploy:deploy /opt/myapp
# Tạo SSH key cho GitHub Actions
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/deploy_key
cat ~/.ssh/deploy_key.pub >> /home/deploy/.ssh/authorized_keys
# Copy ~/.ssh/deploy_key → GitHub Secret VPS_SSH_KEY
Rollback & Zero-Downtime Deploy
Khi deploy lỗi, rollback về version cũ trong 1 lệnh:
# Rollback về commit trước đó
git revert HEAD --no-edit
git push origin main
# GitHub Actions tự chạy deploy
Hoặc rollback thủ công ngay trên VPS:
cd /opt/myapp
git log --oneline -5 # Xem 5 commit gần nhất
git reset --hard <COMMIT_HASH> # Quay về commit cũ
docker compose up -d --build # Build lại
Zero-downtime với Docker:
# docker-compose.yml thêm:
services:
app:
deploy:
update_config:
parallelism: 1
delay: 10s
order: start-first # Start container mới trước → kill cũ sau
failure_action: rollback
Monitoring & Health Check
Mọi service nên có health check endpoint:
// server.js - Node.js health endpoint
app.get('/health', async (req, res) => {
try {
await db.raw('SELECT 1'); // Check DB
await redis.ping(); // Check Redis
res.json({ status: 'ok', uptime: process.uptime() });
} catch (e) {
res.status(503).json({ status: 'error', error: e.message });
}
});
Kết hợp với Uptime Kuma hoặc Grafana để giám sát 24/7:
- Uptime Kuma: Ping
/healthmỗi 60s, alert Telegram khi down. Hướng dẫn cài Uptime Kuma. - Grafana + Prometheus: Dashboard CPU, RAM, req/sec. Hướng dẫn setup monitoring.
Template Cho Các Stack Phổ Biến
Node.js + Express + PostgreSQL
# Dockerfile
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json ./
EXPOSE 3000
CMD ["node", "dist/server.js"]
Python Flask + Redis
# Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"]
Xem thêm: Deploy Python Flask VPS Production
PHP + Nginx + MySQL
# Dockerfile - PHP-FPM
FROM php:8.3-fpm-alpine
RUN docker-php-ext-install pdo pdo_mysql
WORKDIR /var/www/html
COPY . .
# Nginx config trỏ fastcgi_pass tới container php:9000
Static Site (Next.js, Hugo, Astro)
# Build → serve bằng Nginx
FROM node:22-alpine AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
Chi Phí DevOps Stack
| Thành phần | Chi phí | Ghi chú |
|---|---|---|
| VPS (2-4GB RAM) | 40K - 100K/tháng | TrumVPS |
| Docker + Compose | $0 | Open source |
| GitHub Actions | $0 | 2000 phút/tháng miễn phí |
| GitHub Private Repo | $0 | Unlimited |
| Docker Hub | $0 | 1 private image miễn phí |
| Tổng/tháng | 40K - 100K VNĐ | Full DevOps pipeline |
So với các dịch vụ CI/CD trả phí (CircleCI $30/tháng, GitLab CI $19/tháng), setup self-hosted trên VPS tiết kiệm hàng triệu đồng mỗi năm. Với TrumVPS 4GB RAM chỉ 100K/tháng, bạn có DevOps pipeline chuyên nghiệp với chi phí thấp hơn 1 ly cà phê.
Best Practices Cho Solo Dev
- Luôn dùng health check: Docker healthcheck + app
/healthendpoint. Đừng deploy xong rồi "chắc nó chạy". - Environment variables qua .env file: Đừng hardcode password trong code. Dùng
.env+ Docker secrets. - Backup database trước deploy: Thêm step backup trong pipeline.
pg_dumptrước khi migrate. - Feature branch + PR review: Đừng push thẳng main. Mở PR → CI test → merge → CD deploy.
- Log tập trung: Dùng
docker compose logs -fhoặc Portainer để xem log. - Security: KHÔNG dùng root cho deploy. Tạo user riêng, giới hạn quyền. Firewall chỉ mở port cần thiết.
🚀 Sẵn Sàng Deploy Như Pro?
Cần VPS mạnh để chạy Docker + CI/CD pipeline? TrumVPS từ 40K/tháng, 4GB RAM, SSD NVMe, đủ chạy multi-container. Kích hoạt tự động, hỗ trợ 24/7!
Thuê VPS Ngay - Từ 40K