คู่มือการทดลองและติดตั้งระบบในรูปแบบ Multi-Student
คู่มือ Step-by-Step สำหรับผู้เรียนในการติดตั้งและจัดการโปรเจกต์ Parich ERP แยกคอนเทนเนอร์เป็นของตัวเองขนานกันบนเซิร์ฟเวอร์หลัก 1 เครื่อง โดยเข้าผ่านชื่อโดเมนหลักและแยกพอร์ตส่วนตัว
1. Ubuntu Basic Commands (คำสั่ง Ubuntu ที่จำเป็นสำหรับการทำ Workshop)
ก่อนเริ่มต้นกิจกรรม นักเรียนจำเป็นต้องมีความคุ้นเคยกับคำสั่งจัดการเซิร์ฟเวอร์พื้นฐานในระบบ Linux/Ubuntu ดังต่อไปนี้:
1.1 การจัดการไฟล์ โฟลเดอร์ และสิทธิ์ (File System & Permissions)
| คำสั่ง (Command) | คำอธิบาย (Description) | ตัวอย่างการใช้งาน (Example) |
|---|---|---|
cd |
ย้ายตำแหน่งโฟลเดอร์ปัจจุบัน | cd /home/pui/workshop/s1 |
ls -la |
แสดงรายชื่อไฟล์ทั้งหมด (รวมถึงไฟล์ซ่อน เช่น .env, .git) |
ls -la |
cp |
คัดลอกไฟล์หรือโฟลเดอร์ (ใช้ -r สำหรับโฟลเดอร์) |
cp .env.dist .env |
mv |
ย้ายไฟล์ หรือเปลี่ยนชื่อไฟล์ | mv old_name.txt new_name.txt |
chmod |
เปลี่ยนสิทธิ์การเข้าถึงไฟล์/โฟลเดอร์ | chmod 755 script.sh (อนุญาตให้รันได้) |
chown |
เปลี่ยนเจ้าของไฟล์/โฟลเดอร์ | chown pui:pui server_setup_guide.html |
1.2 การวิเคราะห์ระบบและดูทรัพยากร (System Analysis & Resources)
| คำสั่ง (Command) | คำอธิบาย (Description) | ตัวอย่างการใช้งาน (Example) |
|---|---|---|
df -h |
ตรวจสอบพื้นที่ว่างบนหน่วยจัดเก็บข้อมูล (Disk Space) | df -h |
free -m |
ตรวจสอบการใช้งาน RAM (หน่วยเป็น MB) | free -m |
ps aux | grep |
ตรวจสอบสถานะโปรเซสว่าโปรแกรมกำลังรันอยู่หรือไม่ | ps aux | grep nginx |
tail -f |
ดู Log หรือเนื้อหาท้ายไฟล์แบบ Real-time ตามจริง | tail -f /var/log/nginx/error.log |
systemctl |
ตรวจสอบ ควบคุม หรือรีสตาร์ท Service บนระบบ Host | sudo systemctl reload nginx |
1.3 คำสั่ง Docker Compose ควรรู้
| คำสั่ง (Command) | คำอธิบาย (Description) | ตัวอย่างการใช้งาน (Example) |
|---|---|---|
docker compose build |
สั่งบิลด์อิมเมจจาก Dockerfile ล่าสุดในโครงการ | docker compose build |
docker compose up -d |
เริ่มรัน Container ในพื้นหลัง (Background) | docker compose up -d |
docker compose ps |
ตรวจสอบสถานะคอนเทนเนอร์ปัจจุบันในโฟลเดอร์โครงการ | docker compose ps |
docker compose logs -f |
ดูประวัติการบันทึก (Logs) ของคอนเทนเนอร์แบบ Real-time | docker compose logs -f backend |
docker compose down |
สั่งลบและปิดบริการ Container ทั้งหมดในโครงการ | docker compose down |
2. Workshop & Port Matrix (การกำหนดสิทธิ์และพื้นที่ส่วนตัว)
เพื่อให้นักเรียนทุกคนสามารถรันโปรเจกต์ของตัวเองควบคู่กันได้บนระบบปฏิบัติการ Ubuntu เดียวกันโดยไม่ชนกัน เราจะใช้ระบบระบุตัวตน Student ID (เช่น s1, s2, ...) เพื่อแยกพอร์ต คอนเทนเนอร์ และฐานข้อมูล ดังนี้:
Single Domain: demo-parichportal.loolootest.com
การเข้าหน้าเว็บของนักเรียน (s1):
- หน้าบ้าน (Frontend):
https://demo-parichportal.loolootest.com:3001 - หลังบ้าน (Backend API):
https://demo-parichportal.loolootest.com:8001
| Student ID (N) | URL หน้าบ้าน (Frontend) | URL หลังบ้าน (Backend) | Database Name | Redis DB Index |
|---|---|---|---|---|
| s1 | https://demo-parichportal.loolootest.com:3001 | https://demo-parichportal.loolootest.com:8001 | parich_db_s1 | 1 |
| s2 | https://demo-parichportal.loolootest.com:3002 | https://demo-parichportal.loolootest.com:8002 | parich_db_s2 | 2 |
| s3 | https://demo-parichportal.loolootest.com:3003 | https://demo-parichportal.loolootest.com:8003 | parich_db_s3 | 3 |
| sN | https://demo-parichportal.loolootest.com:3000+N | https://demo-parichportal.loolootest.com:8000+N | parich_db_sN | N |
ห้ามใช้พอร์ตหรือชื่อฐานข้อมูลซ้ำกับเพื่อนร่วมชั้นเรียน และระวังอย่าพิมพ์ทับซ้อนข้อมูลคอนเทนเนอร์กันเด็ดขาด
3. Hybrid Architecture (สถาปัตยกรรมระบบไฮบริด)
ระบบของ Parich ERP ทำงานในรูปแบบ Hybrid Architecture เพื่อผลลัพธ์ที่ดีที่สุด:
Docker Container ของผู้เรียน
Nuxt Frontend (พอร์ต 3000+N)
Django Backend (พอร์ต 8000+N)
Host OS (Ubuntu 24.04)
Nginx (Reverse Proxy ประจำพอร์ต)
PostgreSQL 16 & Redis (ร่วมกัน)
จุดประสงค์ของการทำ Hybrid:
- Django & Celery ใน Docker: ช่วยควบคุมสภาพแวดล้อมระบบและ Python runtime 3.14 ให้อยู่แยกเป็นกล่องๆ ของน้องแต่ละคนอย่างปลอดภัย
- PostgreSQL 16 & Redis บน Host OS: เพื่อลดปริมาณการเขียนอ่านไฟล์ในคอนเทนเนอร์ ประสิทธิภาพดีกว่าการรันในตู้ และสะดวกต่อผู้สอนในการจัดการ/ตรวจดู DB
4. OS & Core Setup (การติดตั้งระบบพื้นฐาน)
ขั้นตอนนี้ปกติแล้วผู้สอนจะติดตั้งเตรียมไว้ให้เรียบร้อยแล้ว แต่น้องๆ ควรรู้คำสั่งเหล่านี้สำหรับการตั้งค่าเซิร์ฟเวอร์ Linux ใหม่:
# 1. ติดตั้ง PostgreSQL, Redis, Nginx และ Docker บน Host OS
sudo apt update && sudo apt install -y curl git build-essential libmagic1 postgresql-16 redis-server nginx docker-ce
sudo systemctl enable postgresql redis-server nginx docker
sudo systemctl start postgresql redis-server nginx docker
น้องๆ ทุกคนจะได้รับสิทธิ์เข้ากลุ่ม docker เพื่อไม่ต้องใช้ sudo ทุกครั้งในการสั่งรันคอนเทนเนอร์:
sudo usermod -aG docker $USER && newgrp docker
5. Database Isolation (การจองและแยกแยะฐานข้อมูล)
ให้นักเรียนสร้าง Database และกำหนดสิทธิ์การเข้าใช้งานเป็นของตัวเองบน PostgreSQL ของระบบเซิร์ฟเวอร์ร่วม:
# 1. ล็อกอินเข้าใช้งาน PostgreSQL shell
sudo -u postgres psql
# 2. สร้างฐานข้อมูลของตนเอง (เปลี่ยน sN เป็นรหัสของนักเรียน เช่น s1, s2, s3)
CREATE DATABASE parich_db_sN;
# 3. ให้สิทธิ์การเข้าถึงทั้งหมดแก่ผู้ใช้ django_ci (ซึ่งกำหนดไว้ใน .env)
GRANT ALL PRIVILEGES ON DATABASE parich_db_sN TO django_ci;
\q
6. Workspace & Git Workflow (การเตรียมโค้ด)
ให้นักเรียนโคลน Repository มายังโฟลเดอร์ส่วนตัว โดยแยกโฟลเดอร์ตาม Student ID:
# ตัวอย่างสำหรับนักเรียน s1 (เปลี่ยน path และโฟลเดอร์ตามตัวเอง)
mkdir -p /home/pui/workshop/s1
cd /home/pui/workshop/s1
# โคลนโปรเจกต์จาก Gitea
git clone ssh://git@code.loolootech.com/loolootech/fertilizer-erp.git
cd fertilizer-erp
7. .env Configuration (การตั้งค่า Config ส่วนบุคคล)
เพื่อไม่ให้เกิดการชนกันของระบบ คอนฟิกูเรชันใน `.env` ของแต่ละคนจะต้องแตกต่างกันอย่างสิ้นเชิง ให้นักเรียนสร้าง `.env` จาก Template และเปลี่ยนค่าพารามิเตอร์ดังนี้:
# คัดลอกและสร้างไฟล์คอนฟิกูเรชัน
cd backend
cp .env.dist .env
nano .env
ตัวอย่างการเปลี่ยนค่าตัวแปรในไฟล์ .env ของนักเรียน s1:
# 1. แยกชื่อโครงการในระบบ Docker Compose (สำคัญมากเพื่อป้องกันคอนเทนเนอร์ชนกัน)
COMPOSE_PROJECT_NAME=parich-s1
# 2. ผูกพอร์ตตามตารางข้อ 1 (Frontend 3001, Backend 8001)
HOST_BACKEND_PORT=8001
# 3. ชี้ฐานข้อมูลไปยังตัวที่เราสร้างไว้ในข้อ 5
DB_NAME=parich_db_s1
DB_USER=django_ci
DB_PASSWORD=django_ci_password
DB_HOST=host.docker.internal # เข้าถึงฐานข้อมูลบน Host OS ผ่านเครือข่าย Docker
# 4. แยกฐานข้อมูล Redis Index ของ Celery และ Cache
REDIS_HOST=host.docker.internal
REDIS_PORT=6379
BROKER_URL=redis://host.docker.internal:6379/1
CELERY_RESULT_BACKEND=redis://host.docker.internal:6379/1
8. Build & Deploy (การสตาร์ทระบบผ่าน Docker Compose)
เมื่อตั้งค่าเสร็จแล้ว ให้นักเรียนบิลด์อิมเมจและสตาร์ทตู้ขึ้นมา:
# 1. รัน Deploy Script ของผู้สอนหรือรันคำสั่ง Docker Compose ด้วยตนเอง
docker compose build
docker compose up -d
# 2. ทำการ Migrate ฐานข้อมูลและสร้างข้อมูล Static Assets ของหน้าบ้าน
docker compose exec -T backend python manage.py migrate
docker compose exec -T backend python manage.py collectstatic --no-input
ตรวจสอบสถานะคอนเทนเนอร์ของคุณด้วยคำสั่ง: docker compose ps ซึ่งจะต้องเห็นคอนเทนเนอร์แยกเฉพาะชื่อ เช่น parich-s1-backend และ parich-s1-celery ทำงานตามปกติ
9. Nginx Proxy & SSL (การตั้งค่าจัดเส้นทางพอร์ตนักเรียน)
เพื่อให้สามารถเข้าผ่านชื่อโดเมนหลักทาง HTTPS ได้อย่างปลอดภัย (แก้ปัญหา Not Secure) ผู้สอนหรือนักเรียนจะทำการตั้งค่าเพิ่มบล็อก Nginx บน Host OS เพื่อรับสัญญาณ HTTPS พอร์ตของตัวเองส่งเข้าหา Container ภายในของตนเอง:
ชี้จากโดเมนรวมเข้าหาพอร์ตภายในของน้องแต่ละคนด้วย Config นี้:
# ไฟล์คอนฟิกตัวอย่างสำหรับนักเรียน s1 (/etc/nginx/sites-available/parich-s1)
# --------------------------------------------------
# FRONTEND CONFIG (ชี้พอร์ต 3001 เข้า Nuxt Container)
# --------------------------------------------------
server {
listen 3001 ssl;
server_name demo-parichportal.loolootest.com;
# ใช้ใบรับรอง SSL ร่วมกันของโดเมนหลัก
ssl_certificate /etc/letsencrypt/live/demo-parichportal.loolootest.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/demo-parichportal.loolootest.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3001; # ส่งต่อไปที่พอร์ตภายในของ Frontend Container
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;
}
}
# --------------------------------------------------
# BACKEND CONFIG (ชี้พอร์ต 8001 เข้า Django Container)
# --------------------------------------------------
server {
listen 8001 ssl;
server_name demo-parichportal.loolootest.com;
# ใช้ใบรับรอง SSL ร่วมกันของโดเมนหลัก
ssl_certificate /etc/letsencrypt/live/demo-parichportal.loolootest.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/demo-parichportal.loolootest.com/privkey.pem;
client_max_body_size 75M;
# ดึง Static files ตรงจากไดเรกทอรี Workspace ของผู้เรียน s1 บน Host OS
location /static/ {
alias /home/pui/workshop/s1/fertilizer-erp/backend/static/;
expires 30d;
add_header Cache-Control "public, no-transform";
}
location /media/ {
alias /home/pui/workshop/s1/fertilizer-erp/backend/media/;
expires 7d;
}
location / {
proxy_pass http://127.0.0.1:8001;
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;
}
}
หลังจากบันทึกไฟล์คอนฟิกแล้ว ให้ทำการเปิดใช้งานบล็อคนั้นและสั่ง Reload Nginx:
sudo ln -sf /etc/nginx/sites-available/parich-s1 /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
10. Cron Jobs Isolation (การแยกงานตั้งเวลาของแต่ละคน)
เนื่องจากตัว Cron Daemon ทำงานในระดับ Host OS เพื่อความเสถียร สคริปต์ `deploy.sh` ของน้องๆ จะถูกเขียนให้สร้างคอนฟิกสำหรับนักเรียนแยกกันตามชื่อของโปรเจกต์:
# คอนฟิกใน /etc/cron.d/parich-backend-parich-s1 (สร้างโดยอัตโนมัติ)
0 * * * * root /home/pui/workshop/s1/fertilizer-erp/backend/cron_host.sh calculate_order_target --days-back=3
ช่วยให้น้องมั่นใจได้ว่าคำสั่ง Cron จะยิงงานเข้าไปยังตู้ parich-s1-backend ของตัวเองเท่านั้น ไม่ไปรบกวนข้อมูลของคนอื่น
11. Troubleshooting (การแก้ปัญหาเมื่อพบความผิดพลาด)
11.1 ปัญหา HTTP 403 Forbidden เมื่อเปิดหน้า Django Admin (CSS ไม่โหลด)
ปัญหานี้มักจะเกิดจากการที่สิทธิ์ในการเข้าถึงโฟลเดอร์ static ใน path ของผู้เรียน (เช่น /home/pui/...) ไม่ได้รับสิทธิ์ให้ user www-data ของ Nginx เดินผ่านได้ ให้รันคำสั่งเปิดทางเข้า (Execute) ดังนี้:
# เปิดสิทธิ์การเปิดอ่านและผ่านของโฟลเดอร์ไล่ระดับ
chmod 755 /home/pui
chmod 755 /home/pui/workshop
chmod 755 /home/pui/workshop/s1
chmod 755 /home/pui/workshop/s1/fertilizer-erp
chmod 755 /home/pui/workshop/s1/fertilizer-erp/backend