วิธีติดตั้ง Rocket.Chat ด้วย Docker Compose
คู่มือติดตั้ง Rocket.Chat บน VPS ด้วย Docker Compose พร้อมตั้งค่า MongoDB replica set และ TLS เพื่อป้องกันปัญหาฐานข้อมูลไม่ทำงานตามข้อกำหนดของระบบ
สิ่งที่คุณกำลังสร้าง
ระบบแชทส่วนตัวสำหรับทีมที่คุณเป็นเจ้าของโดยสมบูรณ์: Rocket.Chat ที่รันบน VPS ของคุณเองผ่าน Docker Compose โดยมีการเข้ารหัสด้วย TLS และจัดเก็บทุกข้อความไว้ในฐานข้อมูล MongoDB ซึ่งคุณสามารถสำรองข้อมูลและย้ายข้อมูลได้ Rocket.Chat เป็นซอฟต์แวร์ open-source ที่มีความสามารถเทียบเท่า Slack และ Teams ทั้งการใช้งาน channels, direct messages, threads, การแชร์ไฟล์ รวมถึงการสนทนาด้วยเสียงและวิดีโอ ทั้งหมดนี้ทำงานบนฮาร์ดแวร์ที่คุณเช่าและควบคุมเอง ตัวแอปพลิเคชันเป็นแบบ single container ซึ่งสามารถเริ่มทำงานได้ภายในไม่กี่นาที ปัญหาที่อาจเกิดขึ้นส่วนใหญ่จะเกี่ยวข้องกับฐานข้อมูลที่อยู่คู่กัน ดังนั้นเนื้อหาส่วนใหญ่ในคู่มือนี้จึงเป็นเรื่องเกี่ยวกับ MongoDB โดยเฉพาะข้อกำหนดสำคัญที่มักสร้างความประหลาดใจให้ผู้ใช้งานครั้งแรก: Rocket.Chat จะไม่สามารถทำงานร่วมกับ MongoDB แบบ standalone ได้ แต่จำเป็นต้องใช้รูปแบบ replica set แม้ว่า "set" นั้นจะมีเพียง node เดียวก็ตาม
สิ่งที่ต้องเตรียม และการคำนวณ RAM ที่มักถูกมองข้าม
ควรเลือกขนาดทรัพยากรให้เหมาะสมกับความเป็นจริง ค่าเริ่มต้นที่เหมาะสมสำหรับทีมขนาดเล็กคือ 2 vCPU และ 4 GB of RAM กระบวนการ Node.js ของ Rocket.Chat ใช้ทรัพยากรประมาณ 1 ถึง 1.5 GB และโดยค่าเริ่มต้น MongoDB's WiredTiger cache จะใช้ RAM ประมาณครึ่งหนึ่งของทรัพยากรที่เหลือ หากใช้ VPS ขนาด 2 GB ทั้งสองส่วนจะทำงานได้ในช่วงเริ่มต้น แต่จะเกิดปัญหาเมื่อมี traffic เข้ามาจริง เนื่องจาก MongoDB จะขยายขนาด cache และ Node จะขยายขนาด heap จนทำให้ kernel ไม่มีหน้าหน่วยความจำ (pages) เหลืออยู่ ส่งผลให้ out-of-memory killer สั่งปิด process ที่ใช้ทรัพยากรมากที่สุด ซึ่งมักจะเป็น mongod เมื่อ container แสดงข้อความ Killed และ Docker ทำการ restart ใหม่ จะทำให้ chat server หยุดทำงานทุกๆ ไม่กี่นาทีเมื่อมีภาระงาน (load) ที่ควรจะรับมือได้ การใช้ 2 GB เพียงพอสำหรับการทดสอบใช้งาน 2 คนเท่านั้น แต่ไม่เพียงพอสำหรับใช้งานในระดับทีม หากต้องการรองรับผู้ใช้งานพร้อมกันจำนวนมาก การโทรวิดีโอ หรือประวัติการอัปโหลดที่เพิ่มขึ้น ควรเริ่มต้นที่ 4 GB และควรใช้ 8 GB
คุณต้องเตรียมการ 3 อย่างก่อนเริ่มใช้งาน: ชื่อโดเมนที่มี A record ชี้ไปยัง public IP ของ VPS เนื่องจากฟีเจอร์ real-time และ mobile clients ของ Rocket.Chat จำเป็นต้องใช้ hostname ที่คงที่แทนการใช้ IP เพียงอย่างเดียว, เปิด Port 80 และ 443 ทั้งใน server firewall และ network firewall ของผู้ให้บริการ (ซึ่งมักจะแยกส่วนการควบคุมกันในหน้า control panel ส่วนใหญ่) และ Ubuntu 24.04 KVM VPS ที่ติดตั้งใหม่พร้อมสิทธิ์ root หรือ sudo หากคุณยังลังเลว่า chat server เป็นบริการแรกที่ควรติดตั้งเองหรือไม่ สามารถอ่านรายละเอียดข้อดีและข้อเสียได้ใน คู่มือสิ่งที่ควรติดตั้งเองในปี 2026
ติดตั้ง Docker engine และ Compose plugin
ให้ใช้ apt repository ของ Docker เอง ห้ามใช้ package docker.io ที่มากับ Ubuntu และห้ามใช้ binary ของ Python รุ่นเก่าอย่าง docker-compose โดย Compose รุ่นใหม่เป็น Docker plugin ซึ่งเรียกใช้งานด้วยคำสั่ง docker compose (ใช้ช่องว่างแทนเครื่องหมาย hyphen) ส่วน docker-compose v1 รุ่นเก่าสิ้นสุดอายุการใช้งานแล้ว และจะทำงานผิดพลาดกับ syntax ของ healthcheck และ dependency ที่ระบุไว้ด้านล่าง
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginตรวจสอบว่าติดตั้งทั้งสองส่วนเรียบร้อยแล้ว:
sudo docker version
sudo docker compose versionการที่ docker compose version แสดงผลลัพธ์ประมาณ Docker Compose version v2.x คือการตรวจสอบที่สำคัญ หากเกิดข้อผิดพลาดด้วย docker: 'compose' is not a docker command แสดงว่า plugin ยังไม่ได้ถูกติดตั้ง ซึ่งจะทำให้เกิดปัญหาที่ซับซ้อนในภายหลัง ให้ดำเนินการแก้ไขให้เรียบร้อยในขั้นตอนนี้
The compose file: MongoDB as a single-node replica set
This is the part people get wrong, so read it slowly. Rocket.Chat uses MongoDB change streams to push new messages to connected clients in real time, and change streams are only available on a replica set. Point Rocket.Chat at a plain standalone mongod and it will connect, fail to open a change stream, and restart-loop forever. The fix is not exotic: you run a single, ordinary MongoDB container, but you start it with --replSet and then initialise a one-member set.
Create a working directory and a compose.yml:
services:
mongodb:
image: mongo:8.0
restart: always
command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--oplogSize", "128"]
volumes:
- mongodb_data:/data/db
- mongodb_config:/data/configdb
healthcheck:
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 10s
retries: 12
rocketchat:
image: registry.rocket.chat/rocketchat/rocket.chat:8.5.1
restart: always
depends_on:
mongodb:
condition: service_healthy
environment:
MONGO_URL: "mongodb://mongodb:27017/rocketchat?replicaSet=rs0"
MONGO_OPLOG_URL: "mongodb://mongodb:27017/local?replicaSet=rs0"
ROOT_URL: "https://chat.example.com"
PORT: "3000"
ports:
- "127.0.0.1:3000:3000"
volumes:
mongodb_data:
mongodb_config:A few choices here are deliberate. The Rocket.Chat port is published to 127.0.0.1:3000, not 0.0.0.0 — the app itself has no TLS, so only the reverse proxy on the same box should reach it; binding it to every interface would put a plaintext login page straight on the public internet. MongoDB is not published to the host at all; it is reachable only over Compose's internal network under the name mongodb, which is exactly the hostname the MONGO_URL uses. MONGO_URL carries ?replicaSet=rs0 — leave that off and the driver treats the server as standalone even though it is a replica set, and change streams still fail. MONGO_OPLOG_URL points at the local database where the oplog lives; modern Rocket.Chat prefers change streams, but setting it is harmless and keeps older code paths happy. The depends_on uses condition: service_healthy, so Compose waits until MongoDB answers a ping before it even starts Rocket.Chat — that is what the healthcheck is for.
Pin real version tags on both images — mongo:8.0 and an explicit Rocket.Chat release such as 8.5.1 here — and never use :latest, which turns an unattended docker pull into an accidental, un-migratable upgrade. Check the current stable Rocket.Chat release and the MongoDB versions it supports before you pin. Rocket.Chat publishes a machine-readable info document per release: curl -s https://releases.rocket.chat/8.5.1/info | jq '{compatibleMongoVersions, lts}' returns compatibleMongoVersions: ["8.0"] for 8.5.1, so mongo:8.0 is the only supported engine, plus an lts flag telling you whether that release is a long-term-support build worth pinning for a server you would rather not babysit.
Initialise the replica set
เริ่มการทำงานของ stack:
sudo docker compose up -dRocket.Chat จะหยุดทำงานทันทีและ Docker จะพยายาม restart ต่อเนื่อง ซึ่งเป็นเรื่องปกติ เนื่องจากยังไม่มีการสร้าง replica set ให้สร้าง replica set ด้วยตนเองดังนี้:
sudo docker compose exec mongodb mongosh --eval 'rs.initiate({_id: "rs0", members: [{_id: 0, host: "mongodb:27017"}]})'ผลลัพธ์ที่ถูกต้องคือ { ok: 1 } หลังจากนั้นไม่กี่วินาที node เดียวที่เหลือจะเลือกตัวเองเป็น primary ให้ตรวจสอบด้วยคำสั่ง:
sudo docker compose exec mongodb mongosh --quiet --eval 'rs.status().members[0].stateStr'คุณควรเห็นผลลัพธ์เป็น PRIMARY รายละเอียดที่สำคัญที่สุดในหน้านี้คือ argument host: "mongodb:27017" หากคุณรันคำสั่ง rs.initiate() โดยไม่มีรายการสมาชิก MongoDB จะประกาศชื่อ replica set ด้วย internal hostname ของ container ซึ่งเป็นค่า hash แบบสุ่ม เช่น a1b2c3d4e5f6 เมื่อ Rocket.Chat เชื่อมต่อจาก container ของตนเอง จะไม่สามารถ resolve ชื่อดังกล่าวได้ ส่งผลให้ MongoDB driver เกิดข้อผิดพลาด DNS และทำงานวนลูปพร้อมบันทึก log MongoServerSelectionError: getaddrinfo ENOTFOUND a1b2c3d4e5f6 ตลอดเวลา ให้เริ่มต้นด้วยการระบุ service name ที่ตรงกับ MONGO_URL เสมอ
การบูตครั้งแรก: ตรวจสอบการทำงาน
เมื่อตั้งค่า set เป็น primary แล้ว การ restart Rocket.Chat ครั้งถัดไปจะเชื่อมต่อได้อย่างสมบูรณ์และเริ่มกระบวนการ migrations สำหรับการใช้งานครั้งแรก ให้ติดตามการทำงานผ่าน logs:
sudo docker compose logs -f rocketchatข้อความที่คุณต้องรอคือ startup banner:
+--------------------------------------------+
SERVER RUNNING
Rocket.Chat Version: 8.5.1
NodeJS Version: 22.22.3 - x64
+--------------------------------------------+การบูตครั้งแรกจะใช้เวลานาน เนื่องจากแอปพลิเคชันกำลังรัน database migrations และสร้าง indexes โปรดรอประมาณ 1 ถึง 2 นาที หาก log แสดงข้อความ MongoServerSelectionError: Server selection timed out after 30000 ms ซ้ำพร้อม topology description ประเภท ReplicaSetNoPrimary แสดงว่า replica set ยังไม่ได้ถูก initiate หาก log แสดงข้อความ getaddrinfo ENOTFOUND พร้อมกับ random hash แสดงว่ามีการ initiate ด้วย host ที่ไม่ถูกต้อง ไม่ว่ากรณีใดก็ตาม ให้ย้อนกลับไปทำขั้นตอนก่อนหน้า เมื่อคุณเห็นข้อความ SERVER RUNNING แสดงว่า Rocket.Chat กำลัง listening อยู่ที่ 127.0.0.1:3000 และถึงเวลาที่ต้องตั้งค่า hostname และ TLS สำหรับการใช้งานจริง
Put it behind TLS
ห้ามเปิดใช้งาน Rocket.Chat ผ่าน HTTP ปกติ การเข้าสู่ระบบผ่าน http:// เพียงครั้งเดียวอาจทำให้รหัสผ่านผู้ดูแลระบบของคุณรั่วไหลไปยังผู้ที่ดักฟังข้อมูลในเส้นทางได้ ให้ใช้ reverse proxy บนเครื่องเดียวกันเพื่อทำ TLS termination แล้วจึงส่งต่อข้อมูลไปยัง 127.0.0.1:3000 มีสองสิ่งที่สำคัญคือ: proxy ต้องส่งต่อ WebSocket upgrade headers เนื่องจาก Rocket.Chat ทำงานแบบ real-time และจะใช้งานไม่ได้หากไม่มี headers เหล่านี้ และค่า ROOT_URL ของ container ต้องตรงกับที่อยู่ HTTPS สาธารณะที่ผู้ใช้พิมพ์พอดี
เริ่มต้นด้วยการสร้าง nginx server block แบบ HTTP ปกติ เพื่อทำ proxy ไปยังแอปพลิเคชันและส่งต่อ upgrade headers บันทึกไฟล์ไว้ที่ /etc/nginx/sites-available/rocketchat จากนั้นสร้าง symlink ไปยัง sites-enabled และสั่ง reload:
server {
listen 80;
server_name chat.example.com;
client_max_body_size 100M;
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-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}ในตอนนี้ให้ใช้ port 80 ไปก่อน เนื่องจาก block ที่มี listen 443 ssl; แต่ไม่มี certificate จะไม่ผ่านการตรวจสอบของ sudo nginx -t ให้ reload nginx (sudo nginx -t && sudo systemctl reload nginx) จากนั้นจึงออกใบรับรอง วิธีที่ง่ายที่สุดบน Ubuntu คือ Let's Encrypt TLS certificates with Certbot and nginx: certbot --nginx จะเขียนทับ block ด้านบนเพื่อเพิ่ม listen 443 ssl;, บรรทัด ssl_certificate และการ redirect จาก 80 ไปยัง 443 โดยอัตโนมัติ พร้อมทั้งตั้งเวลาต่ออายุใบรับรองให้คุณ หากคุณรันหลาย container หลัง proxy ตัวเดียว Traefik with automatic TLS for many Docker apps เป็นทางเลือกที่จัดการได้ง่ายกว่า โดยการเพิ่ม router และ service labels ให้กับ service rocketchat เพื่อให้ Traefik จัดการคำขอและต่ออายุใบรับรองให้โดยไม่ต้องใช้ nginx block ไม่ว่าจะใช้วิธีใด ให้ตั้งค่า ROOT_URL เป็น https://chat.example.com ใน compose.yml และรัน sudo docker compose up -d อีกครั้งเพื่อให้ container รับทราบการเปลี่ยนแปลง หากคุณต้องการให้เซิร์ฟเวอร์เข้าถึงได้เฉพาะจากภายในเครือข่ายของคุณเท่านั้นแทนที่จะเป็นอินเทอร์เน็ตสาธารณะ ให้ใช้งาน self-hosted WireGuard VPN on the VPS และผูก proxy ไว้กับที่อยู่ของ tunnel
ขั้นตอนการตั้งค่าเมื่อเริ่มใช้งานครั้งแรก
ไปที่ https://chat.example.com และ Rocket.Chat จะนำทางคุณผ่านขั้นตอนสั้นๆ เริ่มต้นด้วยการตั้งค่า admin account ซึ่งประกอบด้วย ชื่อจริง, username, email และรหัสผ่านที่คาดเดายาก บัญชีนี้เป็นบัญชีเดียวที่มีอยู่ในระบบ ดังนั้นห้ามทำข้อมูลสูญหาย ต่อไปคือการระบุ organisation and server info ได้แก่ ชื่อองค์กร, ประเภทธุรกิจ, ขนาดองค์กร, ชื่อเว็บไซต์ และภาษาเริ่มต้น ข้อมูลเหล่านี้เป็นเพียงการตกแต่งเบื้องต้น ให้กรอกข้อมูลแล้วดำเนินการต่อ จากนั้นคือขั้นตอนสำคัญ คือการเลือกว่าจะ register this workspace กับ Rocket.Chat Cloud หรือจะใช้งานแบบ standalone
การลงทะเบียนจะช่วยให้ใช้งานระบบแจ้งเตือน (push notifications) บนมือถือผ่าน gateway ของ Rocket.Chat และใช้งาน add-on marketplace ได้ แต่ต้องแลกกับการเชื่อมต่อกับ control-plane ของ Rocket.Chat cloud ส่วนการใช้งานแบบ standalone จะทำให้ server เป็นส่วนตัวอย่างสมบูรณ์และไม่มีการพึ่งพาระบบอื่น แต่ระบบแจ้งเตือนบน iOS และ Android จะไม่สามารถใช้งานได้ เนื่องจาก Apple และ Google ไม่อนุญาตให้แอปพลิเคชันที่สร้างขึ้นเองถือครอง push certificates โดยแอปพลิเคชันอย่างเป็นทางการจะต้องส่งข้อมูลผ่าน cloud gateway เท่านั้น ให้เลือกแบบ standalone หากเน้นความเป็นส่วนตัวเป็นหลักและผู้ใช้งานใช้งานผ่าน web app เป็นหลัก หรือเลือกแบบ registration หากจำเป็นต้องใช้งานระบบแจ้งเตือนบนมือถือ คุณสามารถเปลี่ยนการตั้งค่านี้ได้ภายหลังในเมนู Admin
จำกัดสิทธิ์การเข้าถึงก่อนเริ่มเชิญผู้ใช้งาน
Rocket.Chat ตั้งค่าเริ่มต้นเป็น open registration on โดย Registration Form จะถูกตั้งค่าเป็น Public ส่งผลให้ทุกคนที่ทราบ URL สามารถสร้างบัญชีผู้ใช้ได้ ซึ่งเปรียบเสมือนการเปิดช่องทางสาธารณะบน hostname ให้กับบุคคลทั่วไป ให้ไปที่ Admin → Settings → Accounts → Registration แล้วเปลี่ยน Registration Form เป็น Disabled เพื่อสร้างบัญชีด้วยตนเองหรือผ่านลิงก์เชิญ หรือเลือกเป็น Secret URL นอกจากนี้ หากไม่ต้องการสร้างช่องทางอ่านข้อมูลสาธารณะแบบ read-only ให้ปิดการใช้งาน Allow Anonymous Read และ Allow Anonymous Write
ควรตัดสินใจเรื่องสถานที่จัดเก็บไฟล์ที่อัปโหลดด้วยเช่นกัน ค่าเริ่มต้นของ File Upload คือ GridFS ซึ่งจะเก็บรูปภาพและไฟล์แนบทั้งหมดไว้ภายใน MongoDB โดยตรง วิธีนี้ใช้งานง่าย แต่จะทำให้ฐานข้อมูลและทุกๆ mongodump ที่คุณถ่าย มีขนาดใหญ่ขึ้นเรื่อยๆ ตามจำนวนการส่งภาพหน้าจอ (screenshots) ของผู้ใช้งาน คุณสามารถเปลี่ยนไปใช้ local filesystem หรือ S3-compatible bucket ได้ที่ Admin → Settings → File Upload และควรตั้งค่าขนาดไฟล์สูงสุดที่เหมาะสม สำหรับทีมขนาดเล็กการใช้ GridFS สามารถทำได้ แต่ต้องคำนึงว่าไฟล์สำรองข้อมูล (backups) จะมีขนาดใหญ่ขึ้นตามระยะเวลาที่ใช้งาน
การสำรองข้อมูลด้วย mongodump
ข้อมูลทั้งหมดของคุณถูกเก็บไว้ใน volume mongodb_data ห้ามคัดลอก volume ในขณะที่ database กำลังทำงานอยู่ ให้ใช้ mongodump เพื่อสร้าง dump ที่มีความสอดคล้องกัน (consistent dump) และส่งข้อมูลไปยังไฟล์บน host:
sudo docker compose exec -T mongodb mongodump --db rocketchat --archive --gzip > rocketchat-$(date +%F).archive.gzไฟล์ archive ที่ถูกบีบอัดด้วย gzipped นี้คือข้อมูลทั้งหมดใน workspace ของคุณ ประกอบด้วย users, channels, messages, settings และหากคุณตั้งค่าให้เก็บไฟล์ไว้ใน GridFS ไฟล์เหล่านั้นจะรวมอยู่ในนี้ด้วย หากคุณย้ายการเก็บไฟล์ไปไว้ใน filesystem หรือ S3 ให้สำรองข้อมูลส่วนนั้นแยกต่างหาก สำหรับการ restore ลงบนระบบใหม่ ให้ทำการ initialize replica set ก่อน แล้วจึงดำเนินการดังนี้:
sudo docker compose exec -T mongodb mongorestore --archive --gzip --drop < rocketchat-2026-07-15.archive.gzคัดลอกไฟล์ archive ออกจากเครื่อง (off the box) เช่น เก็บไว้ใน object storage หรือ server เครื่องอื่น เพื่อป้องกันไม่ให้ข้อมูลสำรองสูญหายไปพร้อมกับ VPS หากเครื่องหลักพัง และควรตั้งค่า cron ให้รันคำสั่ง dump ทุกคืน การมี backup ที่ไม่เคยผ่านการ restore คือความคาดหวัง ไม่ใช่การสำรองข้อมูลที่แท้จริง ควรทดลอง restore บน VPS ที่ไม่ได้ใช้งานจริงหนึ่งครั้ง เพื่อให้มั่นใจว่าระบบใช้งานได้ก่อนที่จะจำเป็นต้องใช้จริง
Upgrades: pin tags, read the notes, respect the Mongo matrix
กฎสองข้อจะช่วยให้การ upgrade เป็นไปอย่างราบรื่น ข้อแรก ต้อง upgrade Rocket.Chat ทีละหนึ่ง major version เท่านั้น เนื่องจากระบบจะรัน schema migrations เมื่อเริ่มทำงาน และจะไม่ยอมให้ข้าม major version โดยตรง หากคุณพยายามข้ามจาก 6.x ไปยัง 8.x ระบบจะหยุดทำงานพร้อมข้อความ migration error แทนที่จะปล่อยให้ข้อมูลเสียหาย ให้เปลี่ยน image tag ไปยัง release ล่าสุดของ major version ถัดไป อ่าน release notes เพื่อตรวจสอบ breaking changes รัน docker compose up -d และตรวจสอบ log จนกว่าการ migrate จะเสร็จสิ้นก่อนดำเนินการขั้นต่อไป ข้อที่สอง ต้องปฏิบัติตาม MongoDB support matrix เนื่องจาก Rocket.Chat แต่ละ release จะรองรับ MongoDB เวอร์ชันที่กำหนดไว้เท่านั้น โดยสามารถตรวจสอบได้จาก curl -s https://releases.rocket.chat/<version>/info | jq .compatibleMongoVersions หากคุณต้องการเปลี่ยนเวอร์ชัน MongoDB เช่น จาก 7.0 เป็น 8.0 ให้เปลี่ยนทีละหนึ่ง major version และต้องตั้งค่า feature-compatibility version หลังจากการเปลี่ยนแต่ละครั้ง สำหรับ MongoDB 8.0 คำสั่งดังกล่าวจำเป็นต้องระบุ confirm: true มิฉะนั้นระบบจะปฏิเสธการทำงานและแจ้งให้รันคำสั่งใหม่อีกครั้งพร้อมกับ confirmation flag:
sudo docker compose exec mongodb mongosh --eval 'db.adminCommand({setFeatureCompatibilityVersion: "8.0", confirm: true})'ควรทำการ mongodump ก่อนการ upgrade ส่วนประกอบใดก็ตามเสมอ นี่คือวิธีการป้องกันความผิดพลาดที่สำคัญที่สุด
Failure modes, with the exact strings
Rocket.Chat เกิดการ restart-loop ทันทีหลังจาก docker compose up และ docker compose logs rocketchat เต็มไปด้วย MongoServerSelectionError. MongoDB กำลังทำงานอยู่ แต่ driver ไม่สามารถเลือก primary ได้ โดยข้อความ error จะระบุข้อผิดพลาดที่เกิดขึ้น Server selection timed out after 30000 ms ที่มี topology type เป็น ReplicaSetNoPrimary หมายความว่าคุณยังไม่ได้รัน rs.initiate() เนื่องจาก set ยังไม่มี config getaddrinfo ENOTFOUND ตามด้วย hash แบบสุ่ม หมายความว่าคุณเริ่มการทำงานโดยไม่ได้ระบุ host: "mongodb:27017" ทำให้ MongoDB ประกาศ hostname ของ container ที่ไม่สามารถ resolve ได้ ตรวจสอบด้วย sudo docker compose exec mongodb mongosh --eval 'rs.status()': หากเกิด error MongoServerError: no replset config has been received ให้ทำการ initiate set; หากพบสมาชิกที่มี name เป็น hash แบบสุ่ม ให้ทำการ re-initiate ใหม่โดยใช้ service name
Web UI โหลดขึ้นมาได้ แต่หน้า login หมุนค้างและไม่เสร็จสิ้น เปิด browser console เพื่อดู WebSocket connection to 'wss://chat.example.com/websocket' failed ปัญหานี้มักเกิดจาก ROOT_URL ไม่ตรงกัน หรือ proxy ไม่ได้ส่งต่อ upgrade headers ตรวจสอบให้แน่ใจว่า ROOT_URL ตรงกับ public address ที่รวม https:// แล้ว และตรวจสอบว่า nginx location block มีการตั้งค่า Upgrade และ Connection "upgrade" ด้วย proxy_http_version 1.1 หากมีการเปลี่ยนแปลง ให้รัน docker compose up -d ใหม่อีกครั้ง
Container หยุดทำงานต่อเนื่องและ docker compose ps แสดงว่า Restarting docker compose logs แสดงข้อความไม่ครบถ้วน และ sudo dmesg | tail แสดง Out of memory: Killed process 12345 (mongod) จาก oom-killer โดยมี exit code คือ 137 สาเหตุเกิดจาก RAM ไม่พอ วิธีแก้ไขที่แท้จริงคือการใช้ VPS ที่มีขนาดใหญ่ขึ้น โดยมีขนาดขั้นต่ำคือ 4 GB สำหรับการแก้ไขปัญหาเฉพาะหน้า ให้เพิ่ม swap และจำกัด cache ของ MongoDB ด้วย --wiredTigerCacheSizeGB 1 ใน command แต่การใช้ swap เป็นเพียงการชะลอการเกิด OOM เมื่อใช้งานจริงเท่านั้น:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfiledocker compose up ล้มเหลวด้วย error Error response from daemon: driver failed programming external connectivity ... bind: address already in use. มีโปรแกรมอื่นใช้งาน port 3000 อยู่ เช่น container ของ Rocket.Chat ตัวก่อนหน้าที่ปิดไม่สมบูรณ์ หรือแอปพลิเคชันอื่น ตรวจสอบหาโปรแกรมดังกล่าวด้วย sudo ss -ltnp | grep :3000 จากนั้นให้หยุด process หรือ container นั้น หรือเปลี่ยน host side ของการ mapping เป็น 127.0.0.1:3001:3000 และอัปเดต proxy_pass ของ proxy ให้ตรงกัน
FAQ
Does Rocket.Chat really need a MongoDB replica set?
Yes, even for a single server with one database node. Rocket.Chat delivers messages in real time using MongoDB change streams, and change streams are a replica-set-only feature — a standalone mongod cannot open one. You do not need multiple machines; you run one MongoDB container started with --replSet rs0 and initialise a one-member set with rs.initiate(). Skip that step and the driver never finds a primary, so Rocket.Chat restart-loops with MongoServerSelectionError: Server selection timed out and never finishes booting.
How much RAM does self-hosted Rocket.Chat need?
Plan for 4 GB as the practical minimum and 8 GB for a busy team. Rocket.Chat's Node process uses about 1 to 1.5 GB and MongoDB claims roughly half the remaining RAM for its WiredTiger cache, so on a 2 GB box the two collide and the out-of-memory killer terminates mongod under any real load, showing Killed in the logs and exit code 137. Two GB is only enough to evaluate the software with a couple of test users.
How do I put Rocket.Chat behind HTTPS?
Run a reverse proxy on the same VPS that terminates TLS and forwards to 127.0.0.1:3000, and set the container's ROOT_URL to your public https:// address. The proxy must forward the WebSocket upgrade headers or login will hang. Certbot with nginx is the simplest single-app setup; Traefik is cleaner if you run several containers behind one proxy and want automatic certificate management.
How do I back up a self-hosted Rocket.Chat?
Take a consistent database dump with mongodump rather than copying the volume: docker compose exec -T mongodb mongodump --db rocketchat --archive --gzip > backup.archive.gz. That archive contains users, channels, messages, and settings, plus uploaded files if you left storage on GridFS. Copy it off the server, automate it nightly with cron, and rehearse a mongorestore on a throwaway box so you know the restore actually works.
How do I upgrade Rocket.Chat without breaking MongoDB?
Upgrade Rocket.Chat one major version at a time — it runs migrations on boot and refuses to skip majors — and read each release's notes before bumping the pinned image tag. Check which MongoDB versions your target release supports with curl -s https://releases.rocket.chat/<version>/info | jq .compatibleMongoVersions, and when you move MongoDB, step one major at a time and set setFeatureCompatibilityVersion with confirm: true after each hop. Always take a mongodump first.