TL;DR
ECONNREFUSED trên cổng 27017 có nghĩa là ứng dụng của bạn đã cố kết nối đến MongoDB, nhưng dịch vụ không chạy — không có gì đang lắng nghe trên cổng đó. Chín trong mười trường hợp, chỉ cần một lệnh là xong:
# Linux (systemd)
sudo systemctl start mongod
# macOS (Homebrew)
brew services start mongodb-community
# Windows
net start MongoDB
Nguyên nhân gốc rễ
ECONNREFUSED là lỗi ở tầng TCP. Hệ điều hành đã từ chối kết nối một cách chủ động — cổng đang đóng. Điều này xảy ra vì một số lý do:
- Tiến trình
mongodkhông chạy - MongoDB đang lắng nghe trên cổng khác hoặc địa chỉ bind khác
- Tường lửa đang chặn cổng 27017
- Thư mục dữ liệu có quyền không đúng, khiến
mongodkhông thể khởi động - MongoDB bị crash khi khởi động (log sẽ cho biết lý do)
Bước 1 — Kiểm tra xem mongod có đang chạy không
# Linux / macOS
ps aux | grep mongod
# Hoặc kiểm tra trạng thái dịch vụ
sudo systemctl status mongod
Trạng thái inactive (dead) có nghĩa là MongoDB đã dừng — hoặc chưa bao giờ khởi động. Chuyển sang Bước 2.
Bước 2 — Khởi động MongoDB
# Linux (systemd — Ubuntu, Debian, RHEL, CentOS)
sudo systemctl start mongod
sudo systemctl enable mongod # tự động khởi động cùng hệ thống
# macOS (Homebrew)
brew services start mongodb-community
# macOS (thủ công, nếu cài đặt không dùng Homebrew)
mongod --config /usr/local/etc/mongod.conf
# Windows (Command Prompt với quyền Administrator)
net start MongoDB
Bước 3 — Xác nhận cổng đang lắng nghe
Đừng cho rằng việc khởi động đã thành công. Hãy xác nhận MongoDB thực sự đang chấp nhận kết nối trên cổng 27017:
# Linux / macOS
ss -tlnp | grep 27017
# hoặc
lsof -i :27017
# Windows
netstat -ano | findstr 27017
Bạn muốn thấy kết quả như thế này:
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 1234/mongod
Dòng đó xác nhận MongoDB đang lắng nghe. Thử lại ứng dụng của bạn — lỗi ECONNREFUSED sẽ biến mất.
Bước 4 — Nếu mongod không khởi động được, kiểm tra log
Đôi khi systemctl start mongod không báo lỗi nhưng dịch vụ lại tắt ngay lập tức. Log sẽ cho bạn biết chính xác điều gì đã xảy ra:
# Linux
sudo journalctl -u mongod -n 50 --no-pager
# Hoặc kiểm tra trực tiếp file log
sudo tail -n 50 /var/log/mongodb/mongod.log
Các lỗi log phổ biến và cách sửa
Lỗi Permission denied trên thư mục dữ liệu
# Kết quả log:
# exception in initAndListen: NonExistentPath: Data directory /var/lib/mongodb not found.
# Sửa: tạo thư mục và sửa quyền sở hữu
sudo mkdir -p /var/lib/mongodb
sudo chown -R mongodb:mongodb /var/lib/mongodb
sudo chmod 755 /var/lib/mongodb
Cổng đã được sử dụng
# Kết quả log:
# Address already in use for socket: 0.0.0.0:27017
# Tìm tiến trình đang dùng cổng
sudo lsof -i :27017
# Dừng tiến trình nếu là mongod còn sót
sudo kill -9 <PID>
File lock từ lần crash trước
# Kết quả log:
# Unclean shutdown detected. Please visit...
# Xóa file lock
sudo rm /var/lib/mongodb/mongod.lock
sudo mongod --repair --dbpath /var/lib/mongodb
sudo systemctl start mongod
Bước 5 — Kiểm tra bind IP trong mongod.conf
MongoDB đang chạy nhưng vẫn bị từ chối? Địa chỉ bind có thể là vấn đề. Mặc định, MongoDB chỉ lắng nghe trên 127.0.0.1 — kết nối từ các máy chủ hoặc container khác bị từ chối trước khi đến tầng xác thực.
# Mở file cấu hình
sudo nano /etc/mongod.conf
# Tìm phần này:
net:
port: 27017
bindIp: 127.0.0.1 # ← Chỉ chấp nhận kết nối cục bộ
Để cho phép kết nối từ các máy chủ khác — container Docker, máy chủ thứ hai, v.v. — thay đổi bindIp:
net:
port: 27017
bindIp: 0.0.0.0 # Chấp nhận từ mọi IP (dùng kèm quy tắc tường lửa)
Sau đó khởi động lại:
sudo systemctl restart mongod
Lưu ý bảo mật: Chỉ bind vào 0.0.0.0 khi MongoDB nằm sau tường lửa. Không bao giờ để lộ cổng 27017 trực tiếp ra internet mà không có xác thực và giới hạn mạng.
Bước 6 — Kiểm tra tường lửa
Kết nối đến máy chủ MongoDB từ xa? Tường lửa có thể đang âm thầm chặn gói tin trên cổng 27017. Mở cổng một cách tường minh:
# Ubuntu (ufw)
sudo ufw allow 27017/tcp
sudo ufw status
# RHEL/CentOS (firewalld)
sudo firewall-cmd --permanent --add-port=27017/tcp
sudo firewall-cmd --reload
Bước 7 — Docker và Docker Compose
Docker thêm vào một phức tạp về mạng. Bên trong container, 127.0.0.1 trỏ đến chính container đó — không phải máy chủ host. Vì vậy nếu ứng dụng Node.js của bạn chạy trong Docker và MongoDB ở trên host (hoặc trong container khác), chuỗi kết nối cần phải thay đổi:
# Sai — trỏ đến loopback của container, không phải host
MONGODB_URI=mongodb://127.0.0.1:27017/mydb
# Đúng — dùng host.docker.internal (Docker Desktop trên macOS / Windows)
MONGODB_URI=mongodb://host.docker.internal:27017/mydb
# Đúng — nếu MongoDB là service trong docker-compose.yml, dùng tên service
MONGODB_URI=mongodb://mongo:27017/mydb
Ví dụ docker-compose.yml:
services:
app:
build: .
environment:
- MONGODB_URI=mongodb://mongo:27017/mydb
depends_on:
- mongo
mongo:
image: mongo:7
ports:
- "27017:27017"
Kiểm chứng
Dùng mongosh để xác nhận kết nối hoạt động từ đầu đến cuối:
mongosh mongodb://127.0.0.1:27017
# Kết quả mong đợi:
# Connecting to: mongodb://127.0.0.1:27017/
# MongoServerVersion: 7.x.x
# >
Hoặc kiểm tra bằng đoạn code Node.js ngắn sử dụng Mongoose:
const mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/test')
.then(() => console.log('Đã kết nối thành công!'))
.catch(err => console.error(err));
Đã kết nối thành công! trong kết quả có nghĩa là cách sửa đã hiệu quả. Không còn ECONNREFUSED nữa.

