ลดความยุ่งยากในการใช้คลาวด์ พูดคุยกับเจ้าหน้าที่

Home รันแอป Node.js ด้วย PM2 และ Nginx Reverse Proxy

รันแอป Node.js ด้วย PM2 และ Nginx Reverse Proxy

แอป Node.js เช่น Express, Next.js หรือ NestJS ปกติจะฟังอยู่ที่พอร์ตสูงอย่าง 3000 การรันด้วย node app.js ตรง ๆ มีข้อเสียคือแอปจะหยุดเมื่อปิด SSH หรือเกิด Error และไม่เปิดเองหลังรีบูตเครื่อง PM2 เป็น Process Manager ที่แก้ปัญหาเหล่านี้ ส่วน Nginx ทำหน้าที่ Reverse Proxy รับคำขอจากโดเมนจริงที่พอร์ต 80 และ 443 แล้วส่งต่อให้แอป รวมถึงจัดการ SSL ได้

คู่มือนี้ใช้ Ubuntu 22.04 หรือ 24.04 เป็นหลัก และให้คำสั่งสำหรับ AlmaLinux หรือ Rocky Linux ในจุดที่ต่างกัน

สิ่งที่ต้องเตรียม

ขั้นตอนที่ 1: ติดตั้ง Node.js เวอร์ชัน LTS

แพ็กเกจ nodejs ที่มากับ Ubuntu มักเป็นเวอร์ชันเก่า แนะนำให้ติดตั้งจาก Repository ของ NodeSource ตัวอย่างนี้ใช้ Node.js 24 ซึ่งเป็น LTS ในขณะที่เขียน ตรวจเวอร์ชัน LTS ล่าสุดได้ที่ nodejs.org แล้วเปลี่ยนตัวเลขในคำสั่งให้ตรง

Ubuntu

curl -fsSL https://deb.nodesource.com/setup_24.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo apt-get install -y nodejs

AlmaLinux และ Rocky Linux

curl -fsSL https://rpm.nodesource.com/setup_24.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo dnf install -y nodejs

ตรวจสอบเวอร์ชัน

node -v
npm -v

ขั้นตอนที่ 2: เตรียมแอปตัวอย่าง

หากมีแอปอยู่แล้วให้ข้ามไปขั้นตอนที่ 3 ได้ สิ่งสำคัญคือแอปควรฟังที่ 127.0.0.1 ไม่ใช่ทุก Interface เพื่อให้เข้าถึงได้ผ่าน Nginx เท่านั้น

mkdir -p ~/apps/myapp && cd ~/apps/myapp
nano app.js
const http = require('http');
const PORT = process.env.PORT || 3000;

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
  res.end('Hello from Node.js\n');
}).listen(PORT, '127.0.0.1', () => {
  console.log(`Listening on 127.0.0.1:${PORT}`);
});

ขั้นตอนที่ 3: ติดตั้ง PM2 และรันแอป

sudo npm install -g pm2
pm2 start app.js --name myapp
pm2 status

ตาราง pm2 status ควรแสดงแอปชื่อ myapp สถานะ online สำหรับแอปที่เริ่มด้วย npm start ใช้ pm2 start npm --name myapp -- start แทน

ตั้งให้ PM2 เปิดเองเมื่อบูตเครื่อง โดยรันคำสั่งนี้ด้วยผู้ใช้ที่รันแอป (ไม่ใช่ root)

pm2 startup systemd

PM2 จะพิมพ์คำสั่งที่ขึ้นต้นด้วย sudo env PATH=... ออกมาหนึ่งบรรทัด ให้คัดลอกบรรทัดนั้นไปรันตามที่แสดง จากนั้นบันทึกรายการแอปที่กำลังรันอยู่

pm2 save

ทุกครั้งที่เพิ่มหรือลบแอปใน PM2 ต้องรัน pm2 save อีกครั้ง ไม่เช่นนั้นหลังรีบูตจะได้รายการเดิม

คำสั่งที่ใช้บ่อย

คำสั่งหน้าที่
pm2 logs myappดู Log ของแอป
pm2 restart myappรีสตาร์ตแอปหลังอัปเดตโค้ด
pm2 reload myappรีโหลดแบบไม่ขาดช่วง (ใช้ได้กับโหมด cluster)
pm2 monitดู CPU และ RAM ของแต่ละแอปแบบเรียลไทม์

ขั้นตอนที่ 4: ตั้งค่า Nginx เป็น Reverse Proxy

สร้างไฟล์ตั้งค่า บน Ubuntu ใช้ /etc/nginx/sites-available/myapp บน AlmaLinux หรือ Rocky Linux ใช้ /etc/nginx/conf.d/myapp.conf

server {
    listen 80;
    listen [::]:80;
    server_name app.example.com;

    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_read_timeout 60s;
    }
}

บรรทัด Upgrade และ Connection ทำให้ WebSocket (เช่น Socket.IO) ผ่าน Proxy ได้ ส่วน X-Forwarded-* ทำให้แอปรู้ IP จริงของผู้ใช้และรู้ว่าเข้ามาทาง HTTPS หรือไม่ หากใช้ Express ให้ตั้ง app.set('trust proxy', 1) ในแอปด้วย

บน Ubuntu เปิดใช้งานไฟล์ด้วย

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/

จากนั้นทดสอบและโหลดค่าใหม่ (ทุก Distro)

sudo nginx -t
sudo systemctl reload nginx

บน AlmaLinux และ Rocky Linux ที่เปิด SELinux ไว้ Nginx จะเชื่อมต่อไปยังพอร์ตภายในไม่ได้จนกว่าจะอนุญาต

sudo setsebool -P httpd_can_network_connect 1

เมื่อ Proxy ทำงานแล้ว ติดตั้ง HTTPS ได้ตามคู่มือ ติดตั้ง SSL ฟรีจาก Let's Encrypt ด้วย Certbot บน Nginx

ตรวจสอบผลลัพธ์

  • curl http://127.0.0.1:3000 บนเซิร์ฟเวอร์ต้องได้ Hello from Node.js
  • curl -I http://app.example.com จากเครื่องอื่นต้องได้ 200 OK
  • sudo ss -tlnp | grep 3000 ต้องเห็น 127.0.0.1:3000 แปลว่าพอร์ตแอปไม่เปิดสู่ภายนอก
  • สั่ง sudo reboot แล้ว Login กลับมาดู pm2 status ต้องเห็นแอปเป็น online

ปัญหาที่พบบ่อย

502 Bad Gateway

Nginx ต่อแอปไม่ได้ ตรวจว่าแอปยัง online ใน pm2 status และพอร์ตใน proxy_pass ตรงกับพอร์ตที่แอปฟังจริง ดูสาเหตุได้จาก pm2 logs myapp และ /var/log/nginx/error.log บน AlmaLinux หรือ Rocky Linux หาก Log มีคำว่า Permission denied ขณะ connect มักเป็นเรื่อง SELinux ตามขั้นตอนที่ 4

แอปไม่กลับมาหลังรีบูต

ลืมรันคำสั่งที่ pm2 startup พิมพ์ออกมา หรือลืม pm2 save อีกกรณีคือรัน pm2 startup ด้วย root แต่รันแอปด้วยผู้ใช้อื่น ให้ลบด้วย pm2 unstartup systemd แล้วทำขั้นตอนที่ 3 ใหม่ด้วยผู้ใช้ที่ถูกต้อง

แอปรีสตาร์ตวนไม่หยุด

ในคอลัมน์ ของ pm2 status ตัวเลขจะเพิ่มขึ้นเรื่อย ๆ แปลว่าแอป Crash ทันทีหลังเปิด ดูสาเหตุจาก pm2 logs myapp --lines 100 ที่พบบ่อยคือขาด Environment Variable หรือยังไม่ได้รัน npm install

Log ของ PM2 กินพื้นที่ดิสก์

Log เก็บอยู่ที่ ~/.pm2/logs และไม่ถูกหมุนเวียนเอง ติดตั้งโมดูลหมุน Log ด้วย pm2 install pm2-logrotate

หากทำตามขั้นตอนแล้วยังติดปัญหา สามารถติดต่อทีมงาน Support ของ THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/ โดยแจ้งชื่อเซิร์ฟเวอร์ ระบบปฏิบัติการ ขั้นตอนที่ทำไปแล้ว และข้อความ Error ที่พบ เพื่อให้ตรวจสอบได้รวดเร็วขึ้น

ผู้ให้บริการคลาวด์ไทย
เพื่อธุรกิจของคนไทย

"มุ่งมั่น" และ "มั่นคง"
พร้อมรับมือทุกการเติบโต
Trust Cloud
คลาว์ที่ปลอดภัย
คือรากฐานที่มั่นคง
cloud security