Hướng dẫn toàn diện về triển khai ứng dụng lên production sử dụng Claude Code CLI. Từ VPS đến Cloud, từ SSL đến monitoring, tất cả các lệnh đều sẵn sàng để sao chép và chạy.
# Prompt cho Claude:
Kiểm tra dự án trước khi deploy production:
- Chạy tất cả test
- Kiểm tra lỗi TypeScript/lint
- Audit bảo mật dependencies
- Kiểm tra biến môi trường
- Build thử production
# Chạy tất cả test
npm run test
# Chạy test với coverage
npm run test -- --coverage
# Kiểm tra lint
npm run lint
# Kiểm tra TypeScript
npx tsc --noEmit
# Build production
npm run build
# Prompt cho Claude:
Tạo script kiểm tra tất cả environment variables cần thiết trước khi deploy.
So sánh file .env.example với các biến thực tế trong code.
Báo lỗi nếu thiếu biến nào.
# Script kiểm tra env (check-env.sh)
#!/bin/bash
REQUIRED_VARS=(
"DATABASE_URL"
"REDIS_URL"
"JWT_SECRET"
"API_KEY"
"NODE_ENV"
)
MISSING=0
for VAR in "${REQUIRED_VARS[@]}"; do
if [ -z "${!VAR}" ]; then
echo "THIẾU: $VAR"
MISSING=$((MISSING + 1))
else
echo "OK: $VAR"
fi
done
if [ $MISSING -gt 0 ]; then
echo "Thiếu $MISSING biến môi trường. Dừng deploy."
exit 1
fi
echo "Tất cả biến môi trường đã sẵn sàng."
# Prompt cho Claude:
Tối ưu build production cho ứng dụng Node.js/Next.js:
- Minify code
- Tree shaking
- Bundle analysis
- Tối ưu Docker image size
# Phân tích bundle size (Next.js)
npx @next/bundle-analyzer
# Build với report
ANALYZE=true npm run build
# Kiểm tra kích thước build
du -sh .next/
du -sh node_modules/
# Kiểm tra lỗ hổng bảo mật dependencies
npm audit
# Tự động fix lỗ hổng (cẩn thận với breaking changes)
npm audit fix
# Kiểm tra chi tiết
npm audit --json | jq '.vulnerabilities | to_entries[] | select(.value.severity == "critical")'
# Quét bảo mật với Snyk
npx snyk test
# Kiểm tra secrets bị lộ trong code
npx secretlint "**/*"
Tạo script deploy ứng dụng Node.js lên VPS Ubuntu:
- Cài đặt Node.js, Nginx, PM2
- Setup reverse proxy
- SSL với Certbot
- Firewall (UFW)
- Systemd service
# Kết nối SSH đến VPS
ssh root@your-server-ip
# Hoặc dùng SSH key
ssh -i ~/.ssh/my-key.pem ubuntu@your-server-ip
# Cập nhật hệ thống
sudo apt update && sudo apt upgrade -y
# Cài đặt các công cụ cần thiết
sudo apt install -y curl git build-essential ufw
# Tạo user mới
sudo adduser deploy
# Thêm vào group sudo
sudo usermod -aG sudo deploy
# Copy SSH key sang user mới
sudo mkdir -p /home/deploy/.ssh
sudo cp ~/.ssh/authorized_keys /home/deploy/.ssh/
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys
# Chuyển sang user deploy
su - deploy
# Cài đặt Node.js 20 LTS qua NodeSource
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# Kiểm tra phiên bản
node --version
npm --version
# Cài đặt PM2 globally
sudo npm install -g pm2
# Clone repository
cd /home/deploy
git clone https://github.com/your-org/your-app.git app
cd app
# Cài đặt dependencies (production only)
npm ci --production
# Copy file environment
cp .env.example .env
nano .env # Chỉnh sửa biến môi trường
# Build ứng dụng
npm run build
# Khởi chạy ứng dụng
pm2 start dist/main.js --name "my-app" -i max
# Hoặc dùng ecosystem file
cat > ecosystem.config.js << 'EOF'
module.exports = {
apps: [{
name: 'my-app',
script: 'dist/main.js',
instances: 'max',
exec_mode: 'cluster',
env_production: {
NODE_ENV: 'production',
PORT: 3000
},
max_memory_restart: '500M',
log_date_format: 'YYYY-MM-DD HH:mm:ss',
error_file: '/home/deploy/logs/error.log',
out_file: '/home/deploy/logs/out.log'
}]
};
EOF
# Chạy với ecosystem
pm2 start ecosystem.config.js --env production
# Lưu cấu hình PM2 để tự khởi động lại
pm2 save
pm2 startup systemd
# Cài đặt Nginx
sudo apt install -y nginx
# Tạo cấu hình Nginx
sudo tee /etc/nginx/sites-available/my-app << 'EOF'
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
# Giới hạn kích thước upload
client_max_body_size 10M;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
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_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 90;
}
# Cache static files
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
proxy_pass http://127.0.0.1:3000;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
EOF
# Kích hoạt site
sudo ln -s /etc/nginx/sites-available/my-app /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
# Kiểm tra cấu hình
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginx
# Cài đặt Certbot
sudo apt install -y certbot python3-certbot-nginx
# Lấy SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Tự động gia hạn (certbot đã tạo cron tự động)
sudo certbot renew --dry-run
# Bật UFW
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Cho phép SSH, HTTP, HTTPS
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
# Bật firewall
sudo ufw enable
# Kiểm tra trạng thái
sudo ufw status verbose
# Prompt cho Claude:
Tạo script deploy.sh tự động:
- Pull code mới từ git
- Cài dependencies
- Build
- Restart PM2
- Kiểm tra health check
#!/bin/bash
# deploy.sh - Script deploy tự động
set -e
APP_DIR="/home/deploy/app"
LOG_FILE="/home/deploy/logs/deploy.log"
echo "$(date) - Bắt đầu deploy..." | tee -a "$LOG_FILE"
cd "$APP_DIR"
# Pull code mới
echo "Pulling code mới..."
git pull origin main
# Cài dependencies
echo "Cài đặt dependencies..."
npm ci --production
# Build
echo "Building..."
npm run build
# Restart PM2
echo "Khởi động lại ứng dụng..."
pm2 reload my-app
# Health check
echo "Kiểm tra health..."
sleep 3
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/health)
if [ "$HTTP_CODE" -eq 200 ]; then
echo "Deploy thành công! Health check: $HTTP_CODE" | tee -a "$LOG_FILE"
else
echo "CẢNH BÁO: Health check thất bại ($HTTP_CODE)" | tee -a "$LOG_FILE"
pm2 logs my-app --lines 50
exit 1
fi
# Prompt cho Claude:
Tạo cấu hình Terraform cho hạ tầng AWS:
- EC2 instance (t3.medium) trong private subnet
- RDS PostgreSQL trong private subnet
- S3 bucket cho static assets
- ALB (Application Load Balancer)
- VPC với public/private subnets
- Security groups
# main.tf - Ví dụ cấu hình Terraform cơ bản
provider "aws" {
region = "ap-southeast-1"
}
resource "aws_instance" "app" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.medium"
key_name = "my-key"
vpc_security_group_ids = [aws_security_group.app.id]
subnet_id = aws_subnet.private.id
user_data = <<-EOF
#!/bin/bash
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs nginx
npm install -g pm2
EOF
tags = {
Name = "app-production"
}
}
resource "aws_db_instance" "postgres" {
identifier = "app-db"
engine = "postgres"
engine_version = "15"
instance_class = "db.t3.micro"
allocated_storage = 20
db_name = "appdb"
username = "admin"
password = var.db_password
vpc_security_group_ids = [aws_security_group.db.id]
db_subnet_group_name = aws_db_subnet_group.main.name
skip_final_snapshot = false
backup_retention_period = 7
}
resource "aws_s3_bucket" "assets" {
bucket = "my-app-assets-production"
}
# Prompt cho Claude:
Tạo cấu hình deploy AWS ECS Fargate:
- Task definition
- Service
- ALB
- Auto-scaling
- CloudWatch logs
{
"family": "my-app",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "app",
"image": "123456789.dkr.ecr.ap-southeast-1.amazonaws.com/my-app:latest",
"portMappings": [
{
"containerPort": 3000,
"protocol": "tcp"
}
],
"environment": [
{ "name": "NODE_ENV", "value": "production" }
],
"secrets": [
{
"name": "DATABASE_URL",
"valueFrom": "arn:aws:secretsmanager:ap-southeast-1::secret:db-url"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-app",
"awslogs-region": "ap-southeast-1",
"awslogs-stream-prefix": "ecs"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3
}
}
]
}
# Deploy ECS bằng AWS CLI
aws ecs register-task-definition --cli-input-json file://task-definition.json
aws ecs create-service \
--cluster my-cluster \
--service-name my-app \
--task-definition my-app:1 \
--desired-count 2 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-xxx],securityGroups=[sg-xxx],assignPublicIp=ENABLED}" \
--load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:...,containerName=app,containerPort=3000"
# Cập nhật service (deploy phiên bản mới)
aws ecs update-service \
--cluster my-cluster \
--service my-app \
--force-new-deployment
# Prompt cho Claude:
Tạo cấu hình serverless cho API bằng AWS Lambda + API Gateway:
- serverless.yml hoặc SAM template
- Các function handler
- DynamoDB table
- Cấu hình API Gateway
# serverless.yml
service: my-api
provider:
name: aws
runtime: nodejs20.x
region: ap-southeast-1
stage: production
memorySize: 512
timeout: 30
environment:
DATABASE_URL: ${ssm:/my-app/database-url}
JWT_SECRET: ${ssm:/my-app/jwt-secret}
functions:
api:
handler: dist/lambda.handler
events:
- httpApi:
path: /{proxy+}
method: ANY
- httpApi:
path: /
method: ANY
plugins:
- serverless-offline
# Deploy với Serverless Framework
npx serverless deploy --stage production
# Xem logs
npx serverless logs -f api --stage production --tail
# Prompt cho Claude:
Tạo cấu hình deploy Google Cloud Run:
- Dockerfile tối ưu
- cloudbuild.yaml
- Service configuration
- Cloud SQL kết nối
# Build và push Docker image
gcloud builds submit --tag gcr.io/my-project/my-app
# Deploy lên Cloud Run
gcloud run deploy my-app \
--image gcr.io/my-project/my-app \
--platform managed \
--region asia-southeast1 \
--allow-unauthenticated \
--memory 512Mi \
--cpu 1 \
--min-instances 1 \
--max-instances 10 \
--set-env-vars "NODE_ENV=production" \
--set-secrets "DATABASE_URL=db-url:latest,JWT_SECRET=jwt-secret:latest"
# Xem logs
gcloud run services logs read my-app --region asia-southeast1
# Tạo cluster
gcloud container clusters create my-cluster \
--region asia-southeast1 \
--num-nodes 2 \
--machine-type e2-medium
# Deploy ứng dụng
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml
# Tạo resource group và App Service
az group create --name my-rg --location southeastasia
az appservice plan create \
--name my-plan \
--resource-group my-rg \
--sku B1 \
--is-linux
az webapp create \
--resource-group my-rg \
--plan my-plan \
--name my-app \
--runtime "NODE:20-lts"
# Deploy từ GitHub
az webapp deployment source config \
--name my-app \
--resource-group my-rg \
--repo-url https://github.com/your-org/your-app \
--branch main
# Cấu hình biến môi trường
az webapp config appsettings set \
--resource-group my-rg \
--name my-app \
--settings NODE_ENV=production DATABASE_URL=@Microsoft.KeyVault(...)
# Deploy lên Azure Container Apps
az containerapp create \
--name my-app \
--resource-group my-rg \
--environment my-env \
--image myregistry.azurecr.io/my-app:latest \
--target-port 3000 \
--ingress external \
--min-replicas 1 \
--max-replicas 5 \
--cpu 0.5 \
--memory 1.0Gi
# Cài đặt Vercel CLI
npm i -g vercel
# Login
vercel login
# Deploy (lần đầu - tạo project)
vercel
# Deploy production
vercel --prod
Cấu hình vercel.json:
{
"version": 2,
"builds": [
{ "src": "package.json", "use": "@vercel/next" }
],
"env": {
"DATABASE_URL": "@database-url",
"NEXT_PUBLIC_API_URL": "https://api.yourdomain.com"
},
"regions": ["sin1"],
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "no-store" }
]
}
],
"rewrites": [
{ "source": "/api/:path*", "destination": "/api/:path*" }
]
}
# Quản lý biến môi trường
vercel env add DATABASE_URL production
vercel env ls
# Custom domain
vercel domains add yourdomain.com
# Xem logs
vercel logs --follow
# Cài đặt Railway CLI
npm i -g @railway/cli
# Login
railway login
# Tạo project mới
railway init
# Link với project có sẵn
railway link
# Deploy
railway up
# Mở dashboard
railway open
# Xem logs
railway logs
# Thêm service (PostgreSQL, Redis, ...)
railway add
Cấu hình render.yaml:
services:
- type: web
name: my-app
runtime: node
region: singapore
plan: starter
buildCommand: npm ci && npm run build
startCommand: npm start
envVars:
- key: NODE_ENV
value: production
- key: DATABASE_URL
fromDatabase:
name: my-db
property: connectionString
autoDeploy: true
healthCheckPath: /health
databases:
- name: my-db
plan: starter
databaseName: appdb
region: singapore
# Deploy tự động khi push lên GitHub
git push origin main
# Cài đặt Fly CLI
curl -L https://fly.io/install.sh | sh
# Login
fly auth login
# Tạo app mới (tự detect framework)
fly launch
# Deploy
fly deploy
# Xem trạng thái
fly status
# Xem logs
fly logs
# Scale
fly scale count 3
fly scale vm shared-cpu-2x
Cấu hình fly.toml:
app = "my-app"
primary_region = "sin"
[build]
dockerfile = "Dockerfile"
[env]
NODE_ENV = "production"
PORT = "3000"
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 1
[http_service.concurrency]
type = "requests"
hard_limit = 250
soft_limit = 200
[[vm]]
cpu_kind = "shared"
cpus = 1
memory_mb = 512
[checks]
[checks.health]
type = "http"
port = 3000
path = "/health"
interval = "15s"
timeout = "5s"
# Thêm secrets
fly secrets set DATABASE_URL="postgres://..." JWT_SECRET="..."
# Thêm database PostgreSQL
fly postgres create
fly postgres attach my-db
# Cài đặt Certbot (Ubuntu/Debian)
sudo apt install -y certbot python3-certbot-nginx
# Lấy certificate cho Nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Lấy certificate standalone (không có web server)
sudo certbot certonly --standalone -d yourdomain.com
# Gia hạn tất cả certificates
sudo certbot renew
# Kiểm tra lịch gia hạn tự động
sudo systemctl status certbot.timer
# Wildcard certificate (cần DNS challenge)
sudo certbot certonly --manual --preferred-challenges dns \
-d "*.yourdomain.com" -d yourdomain.com
# Prompt cho Claude:
Cấu hình Cloudflare cho domain:
- DNS records (A, CNAME)
- SSL/TLS mode: Full (Strict)
- Page rules
- Firewall rules
- Cache rules
# Sử dụng Cloudflare API
CLOUDFLARE_TOKEN="your-api-token"
ZONE_ID="your-zone-id"
# Thêm DNS record
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $CLOUDFLARE_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"type": "A",
"name": "yourdomain.com",
"content": "your-server-ip",
"ttl": 1,
"proxied": true
}'
# Kiểm tra DNS propagation
dig yourdomain.com A
dig yourdomain.com CNAME
# Kiểm tra SSL certificate
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com </dev/null 2>/dev/null | openssl x509 -noout -dates
# Kiểm tra HTTPS
curl -I https://yourdomain.com
# Prompt cho Claude:
Tạo cấu hình Nginx load balancing cho 3 instance Node.js:
- Upstream với health check
- Rate limiting
- Caching
- WebSocket support
- Security headers
# /etc/nginx/sites-available/my-app
upstream app_backend {
least_conn;
server 127.0.0.1:3001 weight=3;
server 127.0.0.1:3002 weight=2;
server 127.0.0.1:3003 weight=1;
keepalive 32;
}
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=3r/m;
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Security headers
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
# API routes với rate limiting
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Login route với rate limiting chặt hơn
location /api/auth/login {
limit_req zone=login burst=5 nodelay;
proxy_pass http://app_backend;
}
# WebSocket support
location /ws {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
# Cache static files
location /static/ {
proxy_pass http://app_backend;
proxy_cache my_cache;
proxy_cache_valid 200 30d;
expires 30d;
}
}
# docker-compose.yml với Traefik
version: '3.8'
services:
traefik:
image: traefik:v3.0
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.le.acme.email=admin@yourdomain.com"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- letsencrypt:/letsencrypt
app:
image: my-app:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`yourdomain.com`)"
- "traefik.http.routers.app.tls.certresolver=le"
- "traefik.http.services.app.loadbalancer.server.port=3000"
deploy:
replicas: 3
volumes:
letsencrypt:
# Prompt cho Claude:
Tạo cấu hình auto-scaling cho ứng dụng:
- Scale dựa trên CPU usage (>70%)
- Scale dựa trên memory (>80%)
- Scale dựa trên request count
- Min: 2 instances, Max: 10 instances
# Kubernetes HPA (Horizontal Pod Autoscaler)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
# AWS Auto Scaling
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name my-app-asg \
--launch-template LaunchTemplateName=my-app-template,Version='$Latest' \
--min-size 2 \
--max-size 10 \
--desired-capacity 2 \
--vpc-zone-identifier "subnet-xxx,subnet-yyy"
# Tạo scaling policy dựa trên CPU
aws autoscaling put-scaling-policy \
--auto-scaling-group-name my-app-asg \
--policy-name cpu-scale-out \
--policy-type TargetTrackingScaling \
--target-tracking-configuration '{
"TargetValue": 70.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ASGAverageCPUUtilization"
}
}'
# PM2 - tăng memory limit
pm2 restart my-app --max-memory-restart 1G
# Docker - tăng tài nguyên container
docker update --memory=2g --cpus=2 my-app-container
# Kubernetes - cập nhật resource limits
kubectl set resources deployment my-app \
--limits=cpu=2,memory=2Gi \
--requests=cpu=500m,memory=512Mi
# Prompt cho Claude:
Tạo hệ thống monitoring cho production:
- Health check endpoint
- Uptime monitoring
- Response time tracking
- Error rate alerting
// health.controller.js - Health check endpoint
app.get('/health', async (req, res) => {
const healthcheck = {
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage(),
checks: {}
};
try {
// Kiểm tra database
await db.query('SELECT 1');
healthcheck.checks.database = 'ok';
} catch (e) {
healthcheck.checks.database = 'error';
healthcheck.status = 'degraded';
}
try {
// Kiểm tra Redis
await redis.ping();
healthcheck.checks.redis = 'ok';
} catch (e) {
healthcheck.checks.redis = 'error';
healthcheck.status = 'degraded';
}
const statusCode = healthcheck.status === 'ok' ? 200 : 503;
res.status(statusCode).json(healthcheck);
});
# Cài đặt Prometheus + Grafana bằng Docker
cat > docker-compose.monitoring.yml << 'EOF'
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
grafana:
image: grafana/grafana:latest
ports:
- "3001:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=secret
node-exporter:
image: prom/node-exporter:latest
ports:
- "9100:9100"
volumes:
prometheus_data:
grafana_data:
EOF
docker compose -f docker-compose.monitoring.yml up -d
# Cài đặt Sentry SDK
npm install @sentry/node @sentry/profiling-node
// sentry.js - Cấu hình Sentry
const Sentry = require('@sentry/node');
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 0.1, // 10% transactions
profilesSampleRate: 0.1, // 10% profiles
integrations: [
Sentry.httpIntegration(),
Sentry.expressIntegration(),
Sentry.prismaIntegration(),
],
});
# Prompt cho Claude:
Tạo hệ thống log tập trung:
- Structured logging (JSON format)
- Log rotation
- Gửi logs đến ELK Stack hoặc Loki
# PM2 log rotation
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 30
pm2 set pm2-logrotate:compress true
# Xem logs real-time
pm2 logs my-app --lines 100
# Xem logs lỗi
pm2 logs my-app --err --lines 50
# Prompt cho Claude:
Tạo script blue-green deployment:
- Chạy 2 môi trường (blue và green)
- Chuyển traffic sau khi health check thành công
- Rollback nhanh nếu có lỗi
#!/bin/bash
# blue-green-deploy.sh
set -e
CURRENT=$(readlink /home/deploy/current || echo "blue")
if [ "$CURRENT" = "blue" ]; then
NEW="green"
else
NEW="blue"
fi
echo "Triển khai lên môi trường: $NEW"
# Deploy phiên bản mới lên môi trường NEW
cd /home/deploy/$NEW
git pull origin main
npm ci --production
npm run build
# Khởi động môi trường mới
pm2 start ecosystem.config.js --name "app-$NEW" --env production
# Chờ và kiểm tra health
sleep 5
PORT=$([ "$NEW" = "blue" ] && echo "3001" || echo "3002")
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$PORT/health)
if [ "$HTTP_CODE" -eq 200 ]; then
# Chuyển Nginx sang môi trường mới
sudo sed -i "s/127.0.0.1:300[12]/127.0.0.1:$PORT/" /etc/nginx/sites-available/my-app
sudo nginx -t && sudo systemctl reload nginx
# Cập nhật symlink
ln -sfn /home/deploy/$NEW /home/deploy/current
# Dừng môi trường cũ
pm2 stop "app-$CURRENT" 2>/dev/null || true
echo "Deploy thành công! Môi trường active: $NEW"
else
pm2 stop "app-$NEW" 2>/dev/null || true
echo "Health check thất bại. Rollback."
exit 1
fi
# PM2 rolling restart (zero-downtime khi chạy cluster mode)
pm2 reload my-app
# Reload với thời gian chờ
pm2 reload my-app --update-env --wait-ready --listen-timeout 10000
# Prompt cho Claude:
Thiết lập canary deployment với Nginx:
- 10% traffic đến phiên bản mới
- 90% traffic đến phiên bản cũ
- Tăng dần nếu không có lỗi
# /etc/nginx/sites-available/my-app (canary)
upstream app_stable {
server 127.0.0.1:3001;
}
upstream app_canary {
server 127.0.0.1:3002;
}
# Chia traffic 90/10
split_clients "${remote_addr}" $app_version {
90% app_stable;
* app_canary;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
location / {
proxy_pass http://$app_version;
proxy_set_header Host $host;
proxy_set_header X-Canary-Version $app_version;
}
}
# Prompt cho Claude:
Tạo script rollback nhanh cho production:
- Rollback code về commit trước
- Rollback Docker image về tag trước
- Rollback database migration
#!/bin/bash
# rollback.sh - Rollback nhanh
set -e
APP_DIR="/home/deploy/app"
cd "$APP_DIR"
echo "=== ROLLBACK PRODUCTION ==="
echo "Commit hiện tại: $(git rev-parse HEAD)"
# Lấy commit trước đó
PREV_COMMIT=$(git rev-parse HEAD~1)
echo "Rollback về: $PREV_COMMIT"
# Rollback code
git checkout "$PREV_COMMIT"
npm ci --production
npm run build
# Restart ứng dụng
pm2 reload my-app
# Kiểm tra health
sleep 3
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/health)
if [ "$HTTP_CODE" -eq 200 ]; then
echo "Rollback thành công!"
else
echo "CẢNH BÁO: Health check thất bại sau rollback!"
exit 1
fi
# Rollback Docker image
docker pull my-app:previous-tag
docker stop my-app
docker run -d --name my-app my-app:previous-tag
# Rollback Kubernetes
kubectl rollout undo deployment/my-app
# Xem lịch sử rollout
kubectl rollout history deployment/my-app
# Rollback về revision cụ thể
kubectl rollout undo deployment/my-app --to-revision=3
# Rollback migration (Prisma)
npx prisma migrate resolve --rolled-back "migration_name"
# Rollback migration (Knex)
npx knex migrate:rollback
# Rollback migration (TypeORM)
npx typeorm migration:revert
# LƯU Ý QUAN TRỌNG:
# - Luôn backup database TRƯỚC khi deploy
# - Viết migration có thể rollback (up/down)
# - Test rollback trên staging trước
# Script backup database trước khi deploy
pg_dump -h localhost -U postgres -d appdb -F c -f "backup_$(date +%Y%m%d_%H%M%S).dump"
# Restore từ backup
pg_restore -h localhost -U postgres -d appdb -c backup_20260311_100000.dump
Các skill hữu ích cho deploy production:
# DevOps tổng hợp
/engineering-skills:senior-devops
# Kiến trúc AWS
/engineering-skills:aws-solution-architect
# Bảo mật hệ thống
/engineering-skills:senior-security
# Security Operations
/engineering-skills:senior-secops
# Backend performance
/engineering-skills:senior-backend
/engineering-skills:senior-devops
Review cấu hình deploy production của tôi:
- Nginx config tại /etc/nginx/sites-available/my-app
- PM2 ecosystem.config.js
- Dockerfile
- docker-compose.yml
Đề xuất cải thiện về performance và bảo mật.
/engineering-skills:aws-solution-architect
Thiết kế kiến trúc AWS cho ứng dụng SaaS:
- 10,000 users đồng thời
- Database PostgreSQL
- File storage (images, documents)
- Background jobs
- Real-time notifications
Budget: $500/tháng
/engineering-skills:senior-security
Kiểm tra bảo mật cho cấu hình production:
- Review Nginx headers
- Kiểm tra SSL configuration
- Audit firewall rules
- Kiểm tra environment variables
- Review Docker security
Tạo script deploy hoàn chỉnh cho ứng dụng NestJS lên VPS Ubuntu 22.04:
- Server IP: 103.xxx.xxx.xxx
- Domain: api.myapp.com
- Database: PostgreSQL (đã cài trên server)
- Bao gồm: Nginx, PM2, SSL, UFW
- Tạo CI/CD pipeline với GitHub Actions
Tạo Dockerfile tối ưu cho ứng dụng Next.js:
- Multi-stage build
- Non-root user
- Health check
- Tối ưu layer caching
- .dockerignore
Kèm docker-compose.yml với PostgreSQL và Redis
Thiết lập monitoring stack cho production:
- Prometheus thu thập metrics
- Grafana dashboard
- AlertManager gửi alert qua Telegram/Slack
- Node exporter cho system metrics
- Custom metrics cho ứng dụng Node.js
Tất cả chạy bằng Docker Compose
Tạo quy trình migration database an toàn cho production:
- Backup trước khi migrate
- Migration không downtime (online DDL)
- Script rollback cho mỗi migration
- Kiểm tra tương thích ngược
Sử dụng Prisma với PostgreSQL
Cấu hình CDN và caching cho ứng dụng web:
- Cloudflare CDN setup
- Nginx cache cho static files
- Redis cache cho API responses
- Browser cache headers
- Cache invalidation strategy
Tạo cấu hình Kubernetes hoàn chỉnh:
- Deployment với rolling update
- Service (ClusterIP + LoadBalancer)
- Ingress với TLS
- ConfigMap và Secrets
- HPA (auto-scaling)
- PersistentVolumeClaim cho database
- NetworkPolicy
Chuyển đổi ứng dụng Express.js sang serverless:
- AWS Lambda + API Gateway
- Serverless Framework config
- DynamoDB thay PostgreSQL
- S3 cho file upload
- CloudWatch logs
- Ước tính chi phí cho 100K requests/ngày
Tạo cấu hình multi-environment:
- Development (local)
- Staging (giống production)
- Production
Bao gồm:
- Environment variables management
- Database per environment
- CI/CD pipeline cho mỗi environment
- Promotion flow: dev -> staging -> production
Tạo kế hoạch disaster recovery cho production:
- Automated database backup (daily + hourly)
- Cross-region backup
- Recovery time objective (RTO): 30 phút
- Recovery point objective (RPO): 1 giờ
- Runbook cho từng loại sự cố
- Test recovery procedure
Tối ưu performance cho ứng dụng production:
- Analyze và fix slow queries (PostgreSQL)
- Redis caching strategy
- CDN configuration
- Gzip/Brotli compression
- Connection pooling
- Worker threads cho CPU-intensive tasks
Target: Response time < 200ms cho 95th percentile
Hardening bảo mật cho server production Ubuntu:
- SSH hardening (disable root, key only, fail2ban)
- Kernel security parameters (sysctl)
- Automatic security updates
- File integrity monitoring
- Intrusion detection (AIDE/OSSEC)
- Log forwarding
- Firewall rules chi tiết
Tối ưu chi phí cloud cho ứng dụng đang chạy trên AWS:
- Phân tích usage hiện tại
- Reserved instances vs Spot instances
- Right-sizing instances
- S3 lifecycle policies
- CloudFront caching
- Unused resources cleanup
Budget hiện tại: $2000/tháng, target: giảm 30%
[ ] Code đã được review và approve
[ ] Tất cả test pass (unit, integration, e2e)
[ ] Build production thành công
[ ] Dependencies audit (npm audit) - không có critical vulnerability
[ ] Environment variables đã cấu hình đầy đủ
[ ] Database migration đã test trên staging
[ ] Backup database production
[ ] Thông báo team về lịch deploy
[ ] Rollback plan đã sẵn sàng
[ ] Server đã cập nhật OS và security patches
[ ] Firewall rules đã cấu hình (chỉ mở port cần thiết)
[ ] SSL certificate còn hạn (>30 ngày)
[ ] Disk space đủ (>20% free)
[ ] Memory đủ cho ứng dụng
[ ] DNS records đã cấu hình đúng
[ ] Load balancer health check hoạt động
[ ] Không có secrets/credentials trong code
[ ] HTTPS enforced (redirect HTTP -> HTTPS)
[ ] Security headers đã cấu hình (HSTS, CSP, X-Frame-Options, ...)
[ ] Rate limiting đã bật
[ ] CORS đã cấu hình đúng
[ ] Input validation cho tất cả API endpoints
[ ] SQL injection protection
[ ] XSS protection
[ ] Authentication/Authorization hoạt động
[ ] Logs không chứa sensitive data
[ ] Health check endpoint hoạt động (/health)
[ ] Graceful shutdown đã implement
[ ] Error handling và logging đúng
[ ] Database connection pooling
[ ] Cache strategy đã cấu hình
[ ] File upload limits đã set
[ ] Request timeout đã cấu hình
[ ] GZIP/Brotli compression bật
[ ] Uptime monitoring đã setup (UptimeRobot, Pingdom, ...)
[ ] Error tracking đã cấu hình (Sentry, Bugsnag, ...)
[ ] APM đã setup (Datadog, New Relic, ...)
[ ] Log aggregation hoạt động
[ ] Alert rules đã cấu hình (email, Slack, Telegram)
[ ] Dashboard monitoring đã tạo (Grafana)
[ ] Disk space alert (<10% free)
[ ] CPU/Memory alert (>90%)
[ ] Health check pass
[ ] Smoke test thành công (test các luồng chính)
[ ] Response time bình thường
[ ] Error rate không tăng đột biến
[ ] Logs không có lỗi bất thường
[ ] Database connections ổn định
[ ] Thông báo team deploy thành công
[ ] Cập nhật changelog/release notes
[ ] Theo dõi metrics 30 phút sau deploy
[ ] Biết lệnh rollback (đã document)
[ ] Database backup có thể restore
[ ] Previous version image/build còn available
[ ] Team đã biết quy trình rollback
[ ] Hotline/contact list sẵn sàng
| Phương pháp deploy | Phù hợp với | Độ phức tạp | Chi phí |
|---|---|---|---|
| VPS + PM2 + Nginx | MVP, startup nhỏ | Thấp | $5-50/tháng |
| Docker + Docker Compose | Team nhỏ-vừa | Trung bình | $10-100/tháng |
| Vercel/Railway/Render | Frontend, JAMstack | Rất thấp | Free-$50/tháng |
| AWS ECS/Fargate | Team vừa-lớn | Cao | $50-500/tháng |
| Kubernetes (GKE/EKS) | Enterprise, scale lớn | Rất cao | $200-2000+/tháng |
| Serverless (Lambda) | Event-driven, API nhẹ | Trung bình | Pay-per-use |
Nguyên tắc vàng: Bắt đầu đơn giản (VPS hoặc PaaS), tối ưu khi cần thiết. Đừng over-engineer hạ tầng khi chưa có traffic thực tế.
Tài liệu thuộc bộ Claude Code CLI - Hướng dẫn tiếng Việt