Deploy Node.js บน Shared Hosting ด้วย Passenger

Node.js ไม่ได้ใช้ได้แค่บน VPS เท่านั้น Shared Hosting สมัยใหม่หลายเจ้า รวมถึง DirectAdmin รองรับการรัน Node.js App ผ่าน Phusion Passenger ซึ่งเป็น Application Server ที่เชื่อม Apache หรือ Nginx กับ Node.js App ของคุณได้อย่างราบรื่น บทความนี้จะสอนวิธี Deploy Node.js App บน Shared Hosting ทีละขั้นตอน

Phusion Passenger คืออะไร

Phusion Passenger เป็น Multi-language Application Server ที่รองรับ Ruby, Python และ Node.js โดยทำหน้าที่เป็น Middleware ระหว่าง Apache/Nginx กับ App ของคุณ เมื่อมี HTTP Request เข้ามา Passenger จะส่งต่อให้ Node.js Process จัดการ แล้วส่ง Response กลับ ทำให้ไม่ต้องตั้งค่า Reverse Proxy เอง

ตรวจสอบ Node.js บน Hosting

ก่อน Deploy ต้องตรวจสอบว่า Hosting รองรับ Node.js หรือไม่ โดย SSH เข้าไปและรันคำสั่ง:

node --version npm --version which node

ถ้า Hosting ไม่มี SSH หรือไม่รองรับ Node.js ควรพิจารณาใช้ VPS ซึ่งให้ Full Root Access และควบคุมสภาพแวดล้อมได้เต็มที่

หมายเหตุ: Node.js บน Shared Hosting มีข้อจำกัดมากกว่า VPS เพราะแชร์ Resources กับผู้ใช้อื่น ถ้าต้องการ Node.js App ที่รันถาวรหรือมีทราฟฟิกสูง แนะนำใช้ VPS 500 บาท/เดือน ซึ่งให้ควบคุม Node.js ด้วย PM2 ได้เต็มที่

โครงสร้างโฟลเดอร์สำหรับ Node.js บน Passenger

Passenger กำหนด Convention ที่ชัดเจนสำหรับโครงสร้างโฟลเดอร์:

public_html/ ├── app.js ← Entry point หลักของ App ├── package.json ├── node_modules/ └── public/ ← Static files (CSS, images) └── .htaccess ← ตั้งค่า Passenger

ขั้นตอนที่ 1: สร้างไฟล์ app.js

สร้างไฟล์ app.js ใน public_html (หรือโฟลเดอร์ root ของ Domain):

const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'}); res.end('<h1>Node.js บน Shared Hosting สำเร็จแล้ว</h1>'); }); // Passenger จะ inject PORT ผ่าน Environment Variable // ไม่ใช้ port ตายตัว if (typeof(PhusionPassenger) !== 'undefined') { PhusionPassenger.configure({ autoInstall: false }); server.listen('passenger'); } else { server.listen(3000, () => { console.log('Server running on port 3000'); }); }

ขั้นตอนที่ 2: สร้าง package.json

{ "name": "my-nodejs-app", "version": "1.0.0", "main": "app.js", "scripts": { "start": "node app.js" } }

ขั้นตอนที่ 3: ตั้งค่า .htaccess

สร้างไฟล์ .htaccess ใน public_html เพื่อบอก Apache ให้ใช้ Passenger:

PassengerEnabled on PassengerAppRoot /home/username/public_html PassengerAppType node PassengerStartupFile app.js <Directory /home/username/public_html> Allow from all </Directory>

แทนที่ username ด้วย DirectAdmin Username ของคุณ

ขั้นตอนที่ 4: ติดตั้ง Dependencies

SSH เข้าไปแล้วรัน npm install ในโฟลเดอร์ App:

cd ~/public_html npm install

ขั้นตอนที่ 5: Restart Passenger

หลังแก้ไข App ต้อง Restart Passenger โดยสร้างหรือ touch ไฟล์ tmp/restart.txt:

mkdir -p tmp touch tmp/restart.txt

Passenger จะ Restart Process อัตโนมัติเมื่อ detect ไฟล์นี้

Express.js บน Passenger

ถ้าใช้ Express.js แก้ไขการ listen ให้รองรับ Passenger:

const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('Hello from Express on Shared Hosting!'); }); if (typeof(PhusionPassenger) !== 'undefined') { PhusionPassenger.configure({ autoInstall: false }); app.listen('passenger'); } else { app.listen(3000); }

Deploy ผ่าน Node.js Selector บน DirectAdmin (ไม่ต้องแก้ .htaccess เอง)

DirectAdmin รุ่นใหม่หลายเจ้ามี Node.js Selector (CloudLinux) ที่ทำให้สร้างและจัดการ Node.js App ผ่านหน้า UI ได้โดยไม่ต้องเขียน .htaccess เอง วิธีนี้เหมาะกับมือใหม่เพราะคลิกตั้งค่าได้ทุกอย่างจากแผงควบคุม โฮสติ้ง AsiaGB ใช้ DirectAdmin จึงรองรับขั้นตอนนี้

ขั้นตอนการสร้าง Node.js App ผ่าน DirectAdmin Node.js Selector มีดังนี้:

  1. ล็อกอินเข้า DirectAdmin แล้วไปที่หมวด Extra Features → Setup Node.js App (หรือ "Node.js Selector")
  2. คลิกปุ่ม CREATE APPLICATION เพื่อสร้าง App ใหม่
  3. เลือก Node.js version ที่ต้องการจาก dropdown (เช่น 18.x หรือ 20.x LTS)
  4. กำหนด Application root เช่น nodeapp (โฟลเดอร์ที่จะเก็บโค้ด เทียบเท่า /home/username/nodeapp)
  5. กำหนด Application URL ว่าจะให้ App รันที่โดเมนหรือ subdomain ไหน เช่น app.yourdomain.com
  6. กำหนด Application startup file เป็น app.js (Entry point ของ App)
  7. กดปุ่ม CREATE — ระบบจะสร้าง virtualenv และตั้งค่า Passenger ให้อัตโนมัติ

หลังสร้างเสร็จ DirectAdmin จะแสดงคำสั่งสำหรับเข้าสู่ virtual environment (เช่น source /home/username/nodevenv/nodeapp/18/bin/activate) ซึ่งจำเป็นต้องรันก่อนใช้คำสั่ง npm ผ่าน SSH เพื่อให้ใช้ Node.js version ที่ถูกต้อง

ข้อดีของวิธีนี้คือแต่ละ App จะมี virtual environment แยกของตัวเอง ทำให้ติดตั้ง Node.js หลายเวอร์ชันบนบัญชีเดียวกันได้โดยไม่ชนกัน เช่น App เก่ารันบน Node 16 และ App ใหม่รันบน Node 20 พร้อมกัน นอกจากนี้เมื่ออัปโหลดโค้ดเสร็จ คุณยังสามารถอัปโหลดไฟล์ผ่าน File Manager หรือ FTP เข้าโฟลเดอร์ Application root ได้โดยตรง แล้วค่อยกด Restart โดยไม่ต้องใช้ SSH เลย เหมาะกับ workflow ที่ deploy ผ่านการลากไฟล์ขึ้น

ตั้งค่า App: Entry Point, Environment Variable และ npm install ผ่าน UI

เมื่อสร้าง App แล้ว สามารถปรับแต่งค่าต่างๆ ได้จากหน้า Node.js Selector โดยไม่ต้องแตะ Terminal:

Entry Point (Startup File)

ช่อง Application startup file คือไฟล์ที่ Passenger จะเรียกใช้เมื่อ App เริ่มทำงาน โดยปกติคือ app.js ถ้าโปรเจกต์ใช้ชื่ออื่น เช่น server.js หรือ index.js ให้แก้ค่าในช่องนี้ให้ตรง แล้วกด Save จากนั้นกด Restart

Environment Variable

ในหน้า App จะมีส่วน "Add Variable" สำหรับใส่ Environment Variable เช่น NODE_ENV=production, DB_HOST, หรือ API_KEY โดยไม่ต้องเขียนลงไฟล์ .env — ค่าจะถูก inject เข้า process อัตโนมัติเมื่อ Restart App ทำให้ปลอดภัยกว่าการ hardcode ในโค้ด

npm install ผ่าน UI

หน้า Node.js Selector มีปุ่ม "Run NPM Install" ที่จะอ่าน package.json แล้วติดตั้ง dependencies ทั้งหมดให้ในสภาพแวดล้อมที่ถูกต้อง โดยไม่ต้อง SSH เข้าไปรันคำสั่งเอง เหมาะมากสำหรับโฮสติ้งที่ไม่เปิด SSH ถ้าต้องการรัน script อื่นใน package.json ก็ใช้ปุ่ม "Run JS script" ได้เช่นกัน

เคล็ดลับ: ทุกครั้งที่เปลี่ยน Environment Variable, Entry Point หรือเพิ่ม dependency ต้องกด Restart ใน Node.js Selector เสมอ (เทียบเท่า touch tmp/restart.txt) มิฉะนั้น App จะยังรันโค้ดเวอร์ชันเก่าอยู่

ข้อจำกัดของ Node.js บน Shared Hosting เทียบกับ VPS

การรัน Node.js บน Shared Hosting ผ่าน Passenger ใช้งานได้ดีกับ App ขนาดเล็กถึงกลาง แต่มีข้อจำกัดที่ควรเข้าใจก่อนตัดสินใจ ตารางด้านล่างเปรียบเทียบความแตกต่างหลักระหว่าง Shared Hosting กับ VPS:

หัวข้อ Shared Hosting (Passenger) VPS (PM2)
Process Manager ไม่มี (Passenger จัดการเอง, lazy start) PM2 / systemd ควบคุมเต็มที่
กำหนด Port เอง ไม่ได้ (Passenger inject port) ได้ทุก port (3000, 8080 ฯลฯ)
WebSocket / Socket.io จำกัด ขึ้นกับ Server Config รองรับเต็มที่
RAM / CPU แชร์กับผู้ใช้อื่น มีโควต้าจำกัด จัดสรรเฉพาะ (dedicated)
Docker / Background Worker ไม่รองรับ รองรับเต็มรูปแบบ
เหมาะกับ เว็บเล็ก, API เบาๆ, demo Production, Real-time, ทราฟฟิกสูง

โดยสรุป Shared Hosting เหมาะกับการทดลอง รัน API เล็กๆ หรือเว็บส่วนตัวที่ทราฟฟิกไม่สูง ส่วน App ที่ต้องรันถาวร มี background job หรือใช้ WebSocket แบบ Real-time ควรเลือก VPS ที่ให้ Full Root Access

อีกประเด็นที่หลายคนมองข้ามคือเรื่องการ Scale เมื่อทราฟฟิกโต บน Shared Hosting คุณไม่สามารถเพิ่ม CPU หรือ RAM ได้ตามต้องการ เพราะทรัพยากรถูกแชร์และกำหนดโควต้าไว้ตายตัว แต่บน VPS คุณสามารถอัปเกรดแพ็กเกจเพื่อเพิ่ม Core และ RAM ได้ทันที รวมถึงตั้งค่า Cluster Mode ของ PM2 เพื่อรัน Node.js หลาย instance ใช้ทุก CPU Core ได้เต็มประสิทธิภาพ ซึ่งเป็นสิ่งที่ Passenger บน Shared Hosting ทำไม่ได้ หากวางแผนว่า App จะเติบโต การเริ่มต้นบน VPS ตั้งแต่แรกจะช่วยให้ไม่ต้องย้ายระบบกลางทางในอนาคต

ปัญหาที่พบบ่อยและวิธีแก้ (502, Port, Restart)

เมื่อ Deploy Node.js บน Shared Hosting แล้วเจอปัญหา ส่วนใหญ่มาจากไม่กี่สาเหตุที่แก้ได้ไม่ยาก:

1. Error 502 Bad Gateway หรือ Application Error

สาเหตุที่พบบ่อยที่สุดคือ App crash ตอน start — มักเป็นเพราะ dependency ไม่ครบหรือโค้ดมี syntax error ให้ตรวจ log ก่อน:

cd ~/nodeapp tail -n 50 stderr.log

ถ้าเห็น Cannot find module 'xxx' แปลว่ายังไม่ได้รัน npm install ในสภาพแวดล้อมที่ถูกต้อง ให้กด "Run NPM Install" ใน Node.js Selector อีกครั้ง หรือ activate virtualenv ก่อนรัน npm

2. App ไม่ฟัง Port ที่ถูกต้อง

บน Passenger ห้าม hardcode port ตายตัว ต้องให้ App ฟังผ่าน Passenger เสมอ ตรวจให้แน่ใจว่าโค้ดมีเงื่อนไขนี้:

const port = process.env.PORT || 3000; app.listen(port);

Passenger จะกำหนดค่า process.env.PORT ให้เอง ถ้าโค้ดเขียน app.listen(3000) ตายตัวอาจทำงานได้บางครั้งแต่ไม่เสถียร

3. แก้โค้ดแล้วไม่อัปเดต (ต้อง Restart)

Passenger cache process ไว้ การแก้ไฟล์เฉยๆ จะยังไม่มีผลจนกว่าจะ Restart ให้กดปุ่ม Restart ใน Node.js Selector หรือสั่งผ่าน SSH:

mkdir -p ~/nodeapp/tmp touch ~/nodeapp/tmp/restart.txt

4. Memory Limit / App ถูก Kill

ถ้า App กิน RAM เกินโควต้าของ Hosting Plan ระบบจะ kill process ทำให้เกิด 502 เป็นช่วงๆ ตรวจการใช้ memory และลด dependency ที่ไม่จำเป็น ถ้า App ต้องใช้ RAM มากจริงๆ ควรย้ายไป VPS ที่จัดสรร RAM ให้เฉพาะ

ข้อจำกัดของ Node.js บน Shared Hosting

ต้องการ Node.js เต็มรูปแบบ? VPS AsiaGB เริ่มต้น 500 บาท/เดือน ให้ Full Root Access รัน Node.js ด้วย PM2 ได้อิสระ, ติดตั้ง Docker, กำหนด Port เอง เหมาะสำหรับ API Server, Real-time App หรือ Microservices

ต้องการ Node.js เต็มประสิทธิภาพ? ลอง VPS

VPS เริ่มต้น 500 บาท/เดือน Full Root Access, PM2, Docker, กำหนด Port เอง ที่ตั้ง: ไทย, สิงคโปร์

ดูแพ็กเกจ VPS

ดูแพ็กเกจ Hosting ไทย ราคาถูกทั้งหมด →