Deployment & Hosting Strategies 🚀
DevOps Series #21 — by practical-algo.com
🐕 Code เขียนเสร็จแล้ว... แล้วจะเอาขึ้นที่ไหน?
ตัวอย่าง code:
Developer ที่เริ่มต้น:
"เว็บเสร็จแล้ว! ทำยังไงให้คนอื่นเข้าได้?"
- 🤔 ซื้อ server เอง?
- 🤔 ใช้ Vercel/Netlify?
- 🤔 เช่า VPS?
- 🤔 ไป AWS/GCP?
- 🤔 Domain ยังไง? HTTPS ยังไง?
❌ เลือกผิด = จ่ายแพง, ช้า, พังบ่อย
✅ เลือกถูก = ประหยัด, เร็ว, scale ได้
โพสต์นี้จะพาไปรู้จักทุกทางเลือก
ตั้งแต่ free tier ไปจนถึง enterprise-grade
📊 Hosting Options — เปรียบเทียบทุกแบบ
ตัวอย่าง code:
| แบบ | ราคาเริ่มต้น | Control | Scale | ดูแลเอง | เหมาะกับ |
|---|---|---|---|---|---|
| Static Host (Vercel/Netlify) | $0 | ต่ำ | อัตโนมัติ | ไม่ต้อง | Static/SPA, JAMstack |
| PaaS (Railway/Render/Fly.io) | $0-7/mo | ต่ำ-กลาง | อัตโนมัติ | น้อย | Web apps, API, MVP |
| VPS (DO/Linode/Hetzner) | $4-6/mo | สูง | manual | ปานกลาง | custom setup |
| Cloud (AWS/GCP/Azure) | $0-????? | สูงมาก | อัตโนมัติ | เยอะ | Enterprise |
| Bare Metal | $50+/mo | สูงสุด | manual | เยอะมาก | High perf, ML, Gaming |
- Side project / portfolio → Vercel/Netlify (ฟรี)
- Startup MVP → Railway/Render (ง่าย, ถูก)
- ต้อง customize เยอะ → VPS (control ดี, ราคาดี)
- Enterprise / scale → Cloud (AWS/GCP/Azure)
- ML training / gaming → Bare Metal / GPU Cloud
1️⃣ Static Hosting — Vercel / Netlify / Cloudflare Pages
ทำไมถึงฟรี?
ตัวอย่าง code:
Traditional Hosting:
💸 Server ต้องทำงานตลอด = ต้องจ่ายตลอด
Static Hosting:
💰 แค่เก็บไฟล์ + ส่งผ่าน CDN = ถูกมาก (ฟรีได้)
Vercel vs Netlify vs Cloudflare Pages
ตารางนี้ช่วยให้เห็นเร็วมากว่าแต่ละแพลตฟอร์มเด่นคนละมุม: Vercel เหมาะกับ Next.js, Netlify ใช้ง่ายสำหรับทีมเล็ก, ส่วน Cloudflare Pages เด่นเรื่อง edge และต้นทุน bandwidth.
รันคำสั่งเหล่านี้เพื่อ deploy:
| Vercel | Netlify | CF Pages | |
|---|---|---|---|
| จุดเด่น | Next.js best-in-class | ง่ายที่สุด | เร็วที่สุด |
| Free BW | 100 GB/mo | 100 GB/mo | Unlimited |
| Free Builds | 6000 min/mo | 300 min/mo | 500 builds/mo |
| Serverless | ✅ Edge+Node | ✅ Functions | ✅ Workers |
| Edge Runtime | ✅ v8 | ✅ Deno | ✅ v8 |
| Git Integration | GitHub/GitLab/Bitbucket | GitHub/GitLab/Bitbucket | GitHub/GitLab |
| Analytics | ✅ (paid) | ✅ (paid) | ✅ (free basic) |
| Pro Price | $20/mo/seat | $19/mo/seat | $5/mo (paid) |
| เหมาะกับ | Next.js projects | มือใหม่/Static sites | speed + low cost |
Deploy บน Vercel — ง่ายแค่ 3 ขั้นตอน
รันคำสั่งเหล่านี้เพื่อ deploy:
# 1. Install CLI
npm i -g vercel
# 2. Deploy (ครั้งแรก)
cd my-next-app
vercel
# → ตอบคำถาม → ได้ preview URL ทันที
# 3. Deploy production
vercel --prod
# → ได้ URL: my-next-app.vercel.app
# หรือ... แค่ push to GitHub
# Vercel auto-deploy ทุก push ให้เลย 🎉
Vercel Project Config (vercel.json)
ตัวอย่าง code:
{
"framework": "nextjs",
"buildCommand": "npm run build",
"outputDirectory": ".next",
"regions": ["sin1"],
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "no-store" }
]
},
{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "X-Content-Type-Options", "value": "nosniff" }
]
}
],
"rewrites": [
{ "source": "/api/:path*", "destination": "/api/:path*" }
],
"redirects": [
{ "source": "/old-page", "destination": "/new-page", "permanent": true }
]
}
2️⃣ PaaS — Railway / Render / Fly.io
เมื่อต้องการ Backend + Database
รันคำสั่งเหล่านี้เพื่อ deploy:
Static Host: HTML/CSS/JS only ❌ ไม่มี backend
PaaS: Full app + DB + Background jobs ✅
PaaS จัดการให้:
- 🖥️ Server provisioning
- 📦 Container orchestration
- 🗄️ Database management
- 🔐 SSL certificates
- 📊 Logs & monitoring
- 🔄 Auto-deploy from Git
- 📈 Auto-scaling (some)
เปรียบเทียบ PaaS ยอดนิยม
ถ้าคุณกำลังเริ่ม MVP ตารางนี้คือจุดตัดสินใจหลัก: ดู free tier, region, และความสะดวกเรื่อง DB/cron ก่อนเลือก เพื่อไม่ต้องย้ายแพลตฟอร์มเร็วเกินไป.
ตัวอย่าง code:
| Railway | Render | Fly.io | |
|---|---|---|---|
| Free Tier | $5 credit/month | 750 hrs/mo (spin down) | 3 shared VMs free |
| Starter | $5/mo | $7/mo | $0 + usage |
| DB included | ✅ Postgres/MySQL/Redis | ✅ Postgres/Redis | ✅ via Supabase |
| Regions | US/EU/AP | US/EU/SG | 35 regions |
| Cron Jobs | ✅ | ✅ (paid) | ✅ (machines) |
| Private Net | ✅ | ✅ | ✅ WireGuard |
| เหมาะกับ | Startup/Prototype | มือใหม่/Simple app | Global low-latency |
Deploy ด้วย Railway
รันคำสั่งเหล่านี้เพื่อ deploy:
# Install CLI
npm i -g @railway/cli
# Login
railway login
# Init project
railway init
# Add Postgres
railway add --database postgres
# Deploy
railway up
# ได้ URL: my-app.up.railway.app 🎉
Fly.io — Deploy ใกล้ user ที่สุด
รันคำสั่งเหล่านี้เพื่อ deploy:
# Install
curl -L https://fly.io/install.sh | sh
# Login
fly auth login
# Launch (สร้าง fly.toml อัตโนมัติ)
fly launch
# Deploy
fly deploy
# Scale ไปหลาย region
fly regions add sin nrt
fly scale count 2
# ดู status
fly status
ตัวอย่าง code:
# fly.toml
app = "my-api"
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
[[vm]]
cpu_kind = "shared"
cpus = 1
memory_mb = 256
3️⃣ VPS — Virtual Private Server
ทำไมยังมีคนใช้ VPS?
ตัวอย่าง code:
PaaS ง่ายแต่...
- 💸 แพงขึ้นเรื่อยๆ เมื่อ scale
- 🔒 Limited customization
- 📦 Vendor lock-in
- 🐌 Cold starts (บาง service)
VPS ให้:
- 💰 ราคาคงที่ ไม่ว่า traffic เท่าไร
- 🔧 Full root access — ทำอะไรก็ได้
- 📦 Run อะไรก็ได้ (Docker, custom stack)
- 📚 เรียนรู้ Linux/DevOps จริงๆ
Trade-off: ต้องดูแล server เอง
(security updates, backup, monitoring)
VPS Providers เทียบราคา (2025)
ส่วนนี้เหมาะกับคนที่อยากคุมระบบเองและ optimize ค่าใช้จ่ายระยะยาว โดยเฉพาะเมื่อ traffic เริ่มนิ่งและต้องการ performance ที่คาดเดาได้.
ตัวอย่าง code:
| Provider | RAM | vCPU | SSD | ราคา/เดือน | จุดเด่น |
|---|---|---|---|---|---|
| Hetzner | 2 GB | 2 | 40 GB | €3.79 | ถูกที่สุด |
| DigitalOcean | 1 GB | 1 | 25 GB | $6 | เริ่มง่าย |
| Linode | 2 GB | 1 | 50 GB | $5 | community |
| Vultr | 1 GB | 1 | 25 GB | $5 | หลาย region |
| Oracle Cloud | 1 GB | 1 | 50 GB | FREE! | Always Free |
| Contabo | 4 GB | 2 | 50 GB | €4.99 | specs/ราคา |
VPS Setup — จากศูนย์ถึง Production
ไฟล์ configuration มีหน้าตาแบบนี้:
# === Step 1: เข้า server ===
ssh root@your-server-ip
# === Step 2: Security basics ===
# สร้าง user ใหม่ (อย่าใช้ root!)
adduser deploy
usermod -aG sudo deploy
# Setup SSH key
mkdir -p /home/deploy/.ssh
cp ~/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
# ปิด password login + root login
sudo nano /etc/ssh/sshd_config
# PermitRootLogin no
# PasswordAuthentication no
sudo systemctl restart sshd
# === Step 3: Firewall ===
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
# === Step 4: Install Docker ===
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker deploy
# === Step 5: Deploy with Docker Compose ===
ตัวอย่าง code:
# docker-compose.yml
version: "3.8"
services:
app:
image: my-app:latest
build: .
restart: unless-stopped
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
ports:
- "3000:3000"
depends_on:
- db
- redis
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=securepassword
- POSTGRES_DB=mydb
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
pgdata:
รันคำสั่งเหล่านี้เพื่อ deploy:
# Deploy!
docker compose up -d
# Update (zero-downtime)
docker compose pull
docker compose up -d --no-deps --build app
4️⃣ Reverse Proxy — Nginx vs Caddy
ทำไมต้องมี Reverse Proxy?
ตัวอย่าง code:
WITHOUT Reverse Proxy
❌ No HTTPS
❌ No load balancing
❌ No static file caching
❌ Single point of failure
WITH Reverse Proxy
Nginx /
redirect)
✅ HTTPS (auto)
✅ Load balancing
✅ Static file serving
✅ Rate limiting
✅ Compression (gzip/brotli)
✅ WebSocket support
Nginx vs Caddy
ทั้งสองตัวดีมาก แต่ต่างกันที่จุดโฟกัส: Nginx ยืดหยุ่นสูงสำหรับ production ขนาดใหญ่, Caddy ชนะเรื่อง simplicity และ auto-HTTPS สำหรับทีมที่ต้องการความเร็วในการส่งงาน.
ไฟล์ configuration มีหน้าตาแบบนี้:
| Nginx | Caddy | |
|---|---|---|
| HTTPS | ต้อง setup certbot | AUTO! 🎉 |
| Config | ซับซ้อนแต่ยืดหยุ่น | ง่ายมาก |
| Performance | เร็วมาก | เร็วใกล้เคียง |
| Learning Curve | สูง | ต่ำ |
| Load Balancing | ✅ advanced | ✅ basic |
| เหมาะกับ | Production/high traffic | เริ่มต้น/auto-SSL |
Nginx Config — Full Production Setup
ตัวอย่าง code:
# /etc/nginx/sites-available/myapp
# Redirect HTTP → HTTPS
server {
listen 80;
server_name myapp.com www.myapp.com;
return 301 https://$server_name$request_uri;
}
# Main HTTPS server
server {
listen 443 ssl http2;
server_name myapp.com www.myapp.com;
# SSL (managed by certbot)
ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem;
# 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 Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript
text/xml application/xml text/javascript image/svg+xml;
# Static files (serve directly, bypass app)
location /static/ {
alias /var/www/myapp/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# API / App (proxy to Node.js)
location / {
proxy_pass http://localhost: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;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Rate limiting for API
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Health check
location /health {
access_log off;
proxy_pass http://localhost:3000/health;
}
}
# Rate limit zone (ใส่ใน http block)
# limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
Caddy Config — ง่ายกว่าเยอะ!
ตัวอย่าง code:
# Caddyfile — แค่นี้จริงๆ!
myapp.com {
# HTTPS จัดการให้อัตโนมัติ — ไม่ต้องทำอะไร!
# Proxy to app
reverse_proxy localhost:3000
# Static files
handle_path /static/* {
root * /var/www/myapp/static
file_server {
precompressed gzip br
}
}
# Compression
encode gzip zstd
# Security headers
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
Strict-Transport-Security "max-age=31536000; includeSubDomains"
}
# Rate limiting
rate_limit {
zone api {
key {remote_host}
events 10
window 1s
}
}
# Logs
log {
output file /var/log/caddy/myapp.log
format json
}
}
# Multiple sites? แค่เพิ่ม block!
api.myapp.com {
reverse_proxy localhost:4000
}
staging.myapp.com {
reverse_proxy localhost:5000
}
ไฟล์ configuration มีหน้าตาแบบนี้:
# Nginx: ต้องทำ 5 ขั้นตอน
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d myapp.com -d www.myapp.com
sudo nginx -t
sudo systemctl reload nginx
# + ตั้ง cron renew certificate
# Caddy: ขั้นตอนเดียว
sudo apt install caddy
sudo nano /etc/caddy/Caddyfile # ใส่ config ข้างบน
sudo systemctl reload caddy
# HTTPS จัดการให้อัตโนมัติ ✅
5️⃣ SSL/TLS — HTTPS ที่ทุกเว็บต้องมี
SSL/TLS คืออะไร?
ตัวอย่าง code:
HTTP (ไม่มี SSL):
🔓 ใครก็ดักข้อมูลได้ (password, credit card)
HTTPS (มี SSL/TLS):
🔐 เข้ารหัสทุกอย่าง ดักไม่ได้
TLS Handshake (simplified):
⚡ TLS 1.3: handshake เร็วขึ้น (1-RTT vs 2-RTT)
วิธีได้ SSL Certificate
หัวใจคือทำให้ HTTPS กลายเป็น default ตั้งแต่วันแรก เพราะมีผลทั้งความปลอดภัย, SEO, และความน่าเชื่อถือของระบบโดยตรง.
รันคำสั่งเหล่านี้เพื่อ deploy:
| วิธี | ราคา | ความยาก | ใช้เมื่อไร |
|---|---|---|---|
| Let's Encrypt | ฟรี | ง่าย | ทุกเว็บ (default) |
| Caddy auto-SSL | ฟรี | ง่ายที่สุด | ใช้ Caddy |
| Cloudflare SSL | ฟรี | ง่าย | ใช้ CF DNS |
| Vercel/Netlify | ฟรี | อัตโนมัติ | deploy ที่นั่น |
| Commercial | $10-500/yr | manual | enterprise/EV cert |
Let's Encrypt + Certbot
รันคำสั่งเหล่านี้เพื่อ deploy:
# Install certbot
sudo apt install certbot python3-certbot-nginx
# Get certificate (ถ้าใช้ Nginx)
sudo certbot --nginx -d myapp.com -d www.myapp.com
# → ตอบคำถาม → ได้ cert อัตโนมัติ!
# Auto-renew (certbot ตั้งให้แล้ว)
sudo certbot renew --dry-run
# Check cert status
sudo certbot certificates
# Manual renew
sudo certbot renew
sudo systemctl reload nginx
6️⃣ Domain Management — DNS
DNS ทำงานยังไง?
ตัวอย่าง code:
Browser: "myapp.com อยู่ไหน?"
(ISP/Google (.com ?)
8.8.8.8)
┌────────▼───────┐
TLD Server
ns1.cf.com)
┌────────▼───────┐
◄─────────── Auth Server
IP: 1.2.3.4 (Cloudflare)
1.2.3.4
DNS Record Types
ตาราง DNS นี้ควร bookmark ไว้ใช้งานจริง เพราะปัญหา production จำนวนมากมักเริ่มจากการตั้งค่า A/CNAME/TXT ผิดเพียงจุดเดียว.
ตัวอย่าง code:
| Type | ใช้ทำอะไร | ตัวอย่าง |
|---|---|---|
| A | Domain → IPv4 | myapp.com → 1.2.3.4 |
| AAAA | Domain → IPv6 | myapp.com → 2001:db8::1 |
| CNAME | Alias | www → myapp.com |
| MX | Mail server | mail.google.com |
| TXT | SPF/DKIM verify | v=spf1 include:_spf... |
| NS | Nameserver | ns1.cloudflare.com |
| CAA | Allow CA issue cert | issue letsencrypt.org |
ตัวอย่าง DNS Setup — Cloudflare
ตัวอย่าง code:
Cloudflare DNS — myapp.com
Type Name Content TTL Proxy
A @ 1.2.3.4 Auto 🟠 On
A @ 5.6.7.8 Auto 🟠 On
AAAA @ 2001:db8::1 Auto 🟠 On
CNAME www myapp.com Auto 🟠 On
CNAME api api-prod.fly.dev Auto 🟠 On
CNAME blog myblog.vercel.app Auto ⚪ Off
MX @ mx1.google.com Auto N/A
MX @ mx2.google.com Auto N/A
TXT @ v=spf1 include:... Auto N/A
💡 Proxy 🟠 = Traffic ผ่าน Cloudflare (CDN + DDoS protection)
Proxy ⚪ = DNS only (ตรงไป server)
ซื้อ Domain ที่ไหน?
การเลือก registrar ไม่ใช่แค่เรื่องราคาเปิดโดเมนปีแรก แต่ต้องดูค่า renew, UX ตอนจัดการ DNS, และความโปร่งใสเรื่องค่าบริการระยะยาวด้วย.
ตัวอย่าง code:
| Registrar | .com ราคา | จุดเด่น |
|---|---|---|
| Cloudflare | ~$9.77 | at-cost + free DNS |
| Namecheap | ~$9.98 | UI ดี, WhoisGuard ฟรี |
| Porkbun | ~$9.73 | ถูกที่สุด, UI ดี |
| Google Domains | ~$12 | ย้ายไป Squarespace |
| GoDaddy | ~$12-20 | แพง/upsell เยอะ |
7️⃣ CDN — Content Delivery Network
CDN ทำงานยังไง?
ตัวอย่าง code:
WITHOUT CDN:
WITH CDN:
┌──── Edge Tokyo ◄── cached
User in Tokyo ──5ms─┤
- ── Origin US (if not cached)
┌──── Edge London ◄── cached
User in London ─5ms─┤
- ── Origin US (if not cached)
┌──── Edge Singapore ◄── cached
User in Bangkok ─10ms┤
- ── Origin US (if not cached)
⚡ Result: 200ms → 5-10ms (20-40x faster!)
CDN Providers
สำหรับเว็บทั่วไป Cloudflare free plan มักพอแล้ว แต่ถ้าอยู่ใน ecosystem AWS หนัก ๆ การใช้ CloudFront จะบริหารรวมกับระบบเดิมได้ง่ายกว่า.
ตัวอย่าง code:
| Provider | Free Tier | Edge Nodes | จุดเด่น |
|---|---|---|---|
| Cloudflare | ✅ ฟรี | 330+ cities | DDoS/WAF/Workers |
| AWS CloudFront | 1 TB/mo free | 600+ edges | AWS ecosystem |
| Bunny CDN | 14-day trial | 123 PoPs | ถูกมาก |
| Fastly | $50 trial | 90+ PoPs | real-time purge |
Cloudflare Setup (5 นาที)
ตัวอย่าง code:
1. สมัคร cloudflare.com (ฟรี)
3. เปลี่ยน nameserver ที่ registrar ไปเป็น:
- ns1.cloudflare.com
- ns2.cloudflare.com
4. รอ propagate (ไม่เกิน 24 ชม, ปกติ < 1 ชม)
5. เปิด features:
- SSL: Full (Strict)
- Always Use HTTPS: On
- Auto Minify: CSS/JS/HTML
- Brotli: On
- Cache: Standard
- Security Level: Medium
ได้ทันที:
✅ CDN (330+ edge nodes)
✅ DDoS protection
✅ Free SSL
✅ DNS management
✅ Page Rules
✅ Web Analytics
Cache Headers — ควบคุมสิ่งที่ cache
ตัวอย่าง code:
# Nginx — Cache Control headers
# Static assets (images, CSS, JS) — cache นาน
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 365d;
add_header Cache-Control "public, immutable";
}
# HTML — ไม่ cache (ให้ได้ content ใหม่เสมอ)
location ~* \.html$ {
add_header Cache-Control "no-cache, must-revalidate";
}
# API — ไม่ cache เด็ดขาด
location /api/ {
add_header Cache-Control "no-store, no-cache";
}
ตัวอย่าง code:
Cache-Control Cheatsheet:
- public, max-age=31536000, immutable → Static assets (1 ปี)
- public, max-age=3600 → Semi-static (1 ชม)
- private, max-age=0, must-revalidate → User-specific data
- no-cache → ต้อง validate ก่อน serve
- no-store → ห้าม cache เลย (sensitive)
- stale-while-revalidate=60 → Serve stale + fetch new
8️⃣ Deployment Strategies — วิธี Deploy ที่ไม่พัง
Overview
รันคำสั่งเหล่านี้เพื่อ deploy:
❌ Bad Deploy:
1. FTP upload ไฟล์ใหม่ทับของเก่า
2. เว็บพัง 5 นาที
4. User โกรธ
✅ Good Deploy:
1. Deploy version ใหม่ข้างๆ version เก่า
2. ค่อยๆ ส่ง traffic ไป version ใหม่
4. User ไม่รู้เลยว่ามี deploy
Zero-Downtime Deployment = standard ในปี 2025
Rolling Deployment
รันคำสั่งเหล่านี้เพื่อ deploy:
เหมือนเปลี่ยนยางรถ... ทีละล้อ
เริ่มต้น: [v1] [v1] [v1] [v1] ← 4 instances, all v1
Step 1: [v2] [v1] [v1] [v1] ← update 1st instance
↑ ตรวจ health check → ✅ ผ่าน → ไปต่อ
Step 2: [v2] [v2] [v1] [v1] ← update 2nd instance
↑ ตรวจ health check → ✅ ผ่าน → ไปต่อ
Step 3: [v2] [v2] [v2] [v1] ← update 3rd instance
Step 4: [v2] [v2] [v2] [v2] ← done! 🎉
❌ ถ้า Step 2 fail?
Step 2: [v2] [v2] [v1] [v1] ← v2 #2 health check ❌
→ Stop! Rollback v2 #1 and #2 → [v1] [v1] [v1] [v1]
✅ Pros: ง่าย, ใช้ resource เท่าเดิม
❌ Cons: ระหว่าง deploy มี 2 versions วิ่งพร้อมกัน
Blue-Green Deployment
รันคำสั่งเหล่านี้เพื่อ deploy:
มี 2 environments: Blue (production) + Green (staging)
Phase 1: Blue = LIVE ✅
🔵 BLUE 🟢 GREEN
v1 (LIVE) ◄─── (idle)
- App x3 LB
- DB
Phase 2: Deploy v2 to Green
🔵 BLUE 🟢 GREEN
v1 (LIVE) ◄─── v2 (testing)
- App x3 LB ├── App x3
- DB └── DB
↑ ทดสอบ v2 ใน Green
Phase 3: Switch! (แค่เปลี่ยน LB)
🔵 BLUE 🟢 GREEN
v1 (standby) LB v2 (LIVE) ◄───
- App x3 ───► ├── App x3
- DB └── DB
✅ Pros: Zero-downtime, instant rollback
❌ Cons: ต้องมี 2x resources (แพงกว่า)
Canary Deployment
ตัวอย่าง code:
เหมือนนกขมิ้นในเหมือง — ส่งตัวเล็กไปทดสอบก่อน
Step 1: ส่ง 5% traffic ไป v2
Load Balancer
Monitor: error rate, latency, CPU
v1 instances terminated
❌ ถ้า Step 1 มีปัญหา (error spike)?
✅ Pros: ลด blast radius, data-driven decisions
❌ Cons: ซับซ้อน, ต้องมี monitoring ดี
เปรียบเทียบ Deployment Strategies
ตารางนี้ช่วยตัดสินใจเชิงความเสี่ยง: ถ้าต้องการปล่อยงานไวใช้ Rolling, ถ้าระบบ critical มากให้ขยับไป Blue-Green หรือ Canary.
รันคำสั่งเหล่านี้เพื่อ deploy:
| Rolling | Blue-Green | Canary | Recreate | |
|---|---|---|---|---|
| Downtime | Zero | Zero | Zero | มี ❌ |
| Rollback | ช้า | ทันที | เร็ว | ช้า |
| Resource | N+1 | 2N | N+1 | N |
| Risk | ปานกลาง | ต่ำ | ต่ำสุด | สูง |
| Complexity | ต่ำ | ปานกลาง | สูง | ต่ำสุด |
| Use case | ทั่วไป | ต้อง fast rollback | critical systems | dev/test |
Kubernetes Rolling Update Config
ไฟล์ configuration มีหน้าตาแบบนี้:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # สร้าง pod ใหม่เพิ่มได้ 1 ตัว
maxUnavailable: 0 # ห้ามมี pod ลดลง (zero-downtime)
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v2
ports:
- containerPort: 3000
# Health checks — สำคัญมาก!
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
periodSeconds: 10
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
ไฟล์ configuration มีหน้าตาแบบนี้:
# Deploy
kubectl apply -f deployment.yaml
# ดู rollout status
kubectl rollout status deployment/myapp
# Rollback ถ้ามีปัญหา
kubectl rollout undo deployment/myapp
# ดู history
kubectl rollout history deployment/myapp
9️⃣ Full Production Setup — จากศูนย์ถึง Production
Architecture Overview
รันคำสั่งเหล่านี้เพื่อ deploy:
Production Stack
Cloudflare CDN + DNS + DDoS + WAF
(Free Plan)
┌──────▼───────┐
Caddy Reverse Proxy + Auto-SSL
(or Nginx)
┌──────▼───────────────────────────────────┐
Docker Compose
App Postgres Redis
:3000 :5432 :6379
Monitoring: Uptime Kuma + Grafana
Backup: Automated daily to S3/B2
VPS: Hetzner CPX11 (2 vCPU, 2GB RAM) — €3.79/mo
Domain: Cloudflare Registrar — ~$10/yr
Total: ~$15/month for full production stack! 💰
GitHub Actions — Auto Deploy on Push
รันคำสั่งเหล่านี้เพื่อ deploy:
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install & Test
run: |
npm ci
npm run lint
npm test
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy to VPS
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: deploy
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /home/deploy/myapp
git pull origin main
docker compose pull
docker compose up -d --build --no-deps app
docker image prune -f
- name: Health Check
run: |
sleep 10
curl -f https://myapp.com/health || exit 1
- name: Notify on Failure
if: failure()
run: |
curl -X POST "${{ secrets.SLACK_WEBHOOK }}" \
-H 'Content-type: application/json' \
-d '{"text":"❌ Deploy failed! Check GitHub Actions."}'
Automated Backups
รันคำสั่งเหล่านี้เพื่อ deploy:
#!/bin/bash
# backup.sh — run daily via cron
set -euo pipefail
BACKUP_DIR="/home/deploy/backups"
DATE=$(date +%Y-%m-%d_%H%M)
RETENTION_DAYS=7
# Backup PostgreSQL
docker exec postgres pg_dump -U user mydb | gzip > "$BACKUP_DIR/db_${DATE}.sql.gz"
# Backup app data
tar czf "$BACKUP_DIR/data_${DATE}.tar.gz" /home/deploy/myapp/data/
# Upload to Backblaze B2 (cheap!)
rclone copy "$BACKUP_DIR/db_${DATE}.sql.gz" b2:my-backups/db/
rclone copy "$BACKUP_DIR/data_${DATE}.tar.gz" b2:my-backups/data/
# Cleanup old backups
find "$BACKUP_DIR" -name "*.gz" -mtime +$RETENTION_DAYS -delete
echo "✅ Backup completed: $DATE"
รันคำสั่งเหล่านี้เพื่อ deploy:
# Cron job (daily at 3 AM)
crontab -e
0 3 * * * /home/deploy/backup.sh >> /var/log/backup.log 2>&1
🔟 Monitoring — รู้ก่อนที่จะพัง
Uptime Monitoring
ตัวอย่าง code:
# Uptime Kuma — self-hosted uptime monitor
# (ฟรี, สวย, alert ได้)
docker run -d \
--name uptime-kuma \
--restart unless-stopped \
-p 3001:3001 \
-v uptime-kuma:/app/data \
louislam/uptime-kuma:1
# → เข้า http://your-server:3001
# → เพิ่ม monitors:
# - HTTPS: myapp.com (check every 60s)
# - TCP: db server port 5432
# - Docker container health
# → ตั้ง alert: Telegram, Slack, Discord, Email
Simple Health Check Endpoint
ไฟล์ configuration มีหน้าตาแบบนี้:
// Express.js health check
app.get('/health', async (req, res) => {
const health = {
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
checks: {}
};
// Check database
try {
await db.query('SELECT 1');
health.checks.database = 'ok';
} catch (err) {
health.status = 'degraded';
health.checks.database = 'error';
}
// Check Redis
try {
await redis.ping();
health.checks.redis = 'ok';
} catch (err) {
health.status = 'degraded';
health.checks.redis = 'error';
}
// Check disk space
const diskFree = getDiskFreePercent();
health.checks.disk = diskFree > 10 ? 'ok' : 'warning';
const statusCode = health.status === 'ok' ? 200 : 503;
res.status(statusCode).json(health);
});
🛡️ Security Checklist — ก่อนจะ Go Live
ไฟล์ configuration มีหน้าตาแบบนี้:
Production Security Checklist ✅
🔐 SSL/TLS
- [ ] HTTPS everywhere (redirect HTTP → HTTPS)
- [ ] TLS 1.2+ only (disable TLS 1.0/1.1)
- [ ] HSTS header enabled
- [ ] Certificate auto-renewal working
🔒 Server
- [ ] SSH key only (no password login)
- [ ] Non-root user for app
- [ ] Firewall enabled (only 22, 80, 443)
- [ ] Unattended security updates
- [ ] Fail2ban installed
🛡️ Application
- [ ] Environment variables for secrets
- [ ] CORS configured properly
- [ ] Rate limiting on API
- [ ] Input validation & sanitization
- [ ] Security headers (X-Frame, CSP, etc.)
- [ ] Dependencies updated (npm audit)
📊 Monitoring
- [ ] Uptime monitoring active
- [ ] Error tracking (Sentry)
- [ ] Log rotation configured
- [ ] Alerts configured (Telegram/Slack)
💾 Backup
- [ ] Daily automated backups
- [ ] Backups stored off-server
- [ ] Restore tested recently
- [ ] Backup monitoring (alert on failure)
🗺️ Decision Flowchart — เลือก Hosting ยังไง?
ตัวอย่าง code:
เริ่มต้น: มี project อะไร?
- Static site / SPA / Next.js?
- ใช้ Next.js → Vercel (free)
- Static HTML → Cloudflare Pages (free, fastest)
- อื่นๆ → Netlify (free, easiest)
- Full-stack app + DB?
- MVP / prototype?
└── Railway or Render (ง่ายที่สุด)
- ต้อง customize?
└── VPS + Docker Compose
- ต้อง scale globally?
└── Fly.io (multi-region)
- Enterprise?
- AWS/GCP/Azure + Kubernetes
- API only?
- Lightweight → Cloudflare Workers / Vercel Edge
- Node/Python → Railway or Fly.io
- Complex → VPS or Cloud
- ML / GPU workloads?
- Inference → Modal, Replicate, RunPod
- Training → Lambda Labs, Vast.ai
- Enterprise → AWS SageMaker, GCP Vertex
🔑 Key Takeaways
แนวคิดสำคัญของบทนี้คือ “เลือกให้เหมาะกับ stage ของโปรเจกต์” มากกว่าการไล่ใช้ของใหญ่ตั้งแต่วันแรก แล้วค่อยยกระดับ architecture ตามภาระงานจริง.
- เริ่มจากง่ายไปยาก — Vercel/Netlify → PaaS → VPS → Cloud
- HTTPS ฟรีทุกที่ — Let's Encrypt, Caddy auto-SSL, Cloudflare
- Cloudflare = must-have — CDN + DNS + DDoS ฟรี
- Caddy ง่ายกว่า Nginx — สำหรับ project ที่ไม่ต้อง fine-tune มาก
- Zero-downtime deploy เป็น standard — Rolling update เป็นค่า default
- Canary deploy สำหรับ critical systems — ลด blast radius
- Blue-Green สำหรับ instant rollback — แต่ต้องมี 2x resources
- VPS + Docker Compose + Caddy = sweet spot — $5-15/mo ได้ production-grade
- Automate everything — CI/CD, backups, monitoring, SSL renewal
- Monitor before you deploy — ถ้าไม่ monitor = ไม่รู้ว่าพัง
📌 This is #21 in our DevOps & Full-Stack series
📚 Series ทั้งหมด:
- Git Branching — แตก branch ยังไงให้เป็นระบบ
- CI/CD Pipeline — จาก commit ถึง production
- Docker vs VMs — Container คืออะไร ทำไมต้องใช้
- API Lifecycle — Request เดินทางยังไง
- Kubernetes — จัดการ container ระดับ production
- Networking — DNS, TCP, Load Balancer, Firewall
- Infrastructure as Code — Terraform & Ansible
- Monitoring & Observability — Logs, Metrics, Traces
- Linux & Shell Essentials — พื้นฐานที่ DevOps ต้องรู้
- DevSecOps & Security — Shift Left, OWASP, Secrets
- Testing Strategies — Pyramid, TDD, Load, Chaos
- GitOps & ArgoCD — Git-driven Deployments
- Cloud Architecture — AWS, GCP, Azure Fundamentals
- SRE — Site Reliability Engineering
- GitHub Actions Workflow — Advanced CI/CD
- Automated Testing — Unit, Integration, E2E
- Database Design & SQL — Normalization, Indexing, Query Optimization
- Authentication & Authorization — JWT, OAuth, RBAC
- Web Architecture & Design Patterns — Monolith vs Microservices
- Frontend Performance & Modern Frameworks
- Deployment & Hosting Strategies — Vercel to Bare Metal ← 📍 อยู่ตรงนี้