Lỗi Gặp Phải
Bạn chạy ứng dụng Node.js và nó bị crash — ngay lập tức hoặc giữa chừng một request — với thông báo kiểu như:
Error: connect ECONNREFUSED 127.0.0.1:5432
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1187:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 5432
}
Số port thay đổi tùy theo dịch vụ bạn đang kết nối: 5432 cho PostgreSQL, 3306 cho MySQL, 6379 cho Redis, 27017 cho MongoDB, hoặc port tùy chỉnh mà dịch vụ của bạn sử dụng. Nguyên nhân gốc rễ luôn giống nhau: Node.js cố mở một kết nối TCP đến địa chỉ và port đó, nhưng không có gì phản hồi.
Nguyên Nhân Gốc Rễ
- Database hoặc dịch vụ đơn giản là không chạy.
- Dịch vụ đang chạy nhưng trên port khác với những gì config của bạn kỳ vọng.
- Dịch vụ được bind vào một interface khác (ví dụ:
::1IPv6 thay vì127.0.0.1IPv4). - Firewall hoặc Docker network đang chặn kết nối.
- Ứng dụng của bạn khởi động trước khi database hoàn tất quá trình boot (race condition trong Docker Compose).
- Sai host/port trong connection string hoặc file
.env.
Bước 1 — Kiểm Tra Dịch Vụ Có Đang Chạy Không
Cách này giải quyết được 90% trường hợp.
Linux / macOS
# Kiểm tra xem có gì đang lắng nghe trên port mục tiêu không
sudo ss -tlnp | grep 5432
# hoặc
sudo lsof -i :5432
Không có kết quả nghĩa là dịch vụ đang dừng. Hãy khởi động nó:
# PostgreSQL
sudo systemctl start postgresql
# MySQL / MariaDB
sudo systemctl start mysql
# Redis
sudo systemctl start redis
Windows
netstat -ano | findstr :5432
Không thấy gì? Mở Services (services.msc) và khởi động dịch vụ tương ứng, hoặc dùng lệnh khởi động riêng của ứng dụng đó.
Bước 2 — Xác Minh Config Kết Nối
Dịch vụ đã chạy? Bây giờ hãy chắc chắn ứng dụng của bạn đang trỏ đúng chỗ. Một file .env cũ hoặc một ký tự gõ sai cũng đủ để phá vỡ kết nối.
# Ví dụ file .env
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=myuser
DB_PASSWORD=secret
DB_NAME=mydb
Đối chiếu với những gì thực sự có trong code kết nối của bạn:
// pg (node-postgres)
const { Pool } = require('pg');
const pool = new Pool({
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
});
In ra giá trị thực tế trước khi kết nối — đừng đoán mò:
console.log('Connecting to', process.env.DB_HOST, ':', process.env.DB_PORT);
Bước 3 — Kiểm Tra Bind Address (IPv4 vs IPv6)
Một số cài đặt chỉ bind vào ::1 (IPv6 loopback), trong khi ứng dụng của bạn lại kết nối tới 127.0.0.1 (IPv4). Trông chúng giống nhau, nhưng thực ra không phải — đây là hai socket hoàn toàn riêng biệt.
sudo ss -tlnp | grep 5432
# Nếu bạn thấy *:5432 hoặc :::5432 — nghĩa là chỉ có IPv6
Cách nhanh: chuyển host thành localhost và để Node.js tự resolve, hoặc dùng trực tiếp ::1:
DB_HOST=localhost # Node tự resolve sang interface nào khả dụng
Hoặc, hãy bảo PostgreSQL bind cả hai interface bằng cách chỉnh postgresql.conf:
listen_addresses = 'localhost' # lắng nghe trên cả 127.0.0.1 và ::1
Bước 4 — Race Condition Trong Docker Compose
Bạn đang chạy Node.js và database cùng nhau trong Docker Compose? Container app của bạn gần như chắc chắn khởi động trước khi DB sẵn sàng. depends_on không giúp được ở đây — nó chỉ chờ container khởi động, không phải chờ PostgreSQL bên trong hoàn tất quá trình boot.
Cách khắc phục là dùng health check kết hợp với condition: service_healthy:
services:
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: secret
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
app:
build: .
depends_on:
db:
condition: service_healthy
environment:
DB_HOST: db
DB_PORT: 5432
Lưu ý: trong Docker Compose, hãy dùng tên service (db) làm host, không phải 127.0.0.1.
Bước 5 — Thêm Retry Logic Vào Ứng Dụng
Một lỗi ECONNREFUSED không nên làm sập toàn bộ tiến trình của bạn. Hãy thêm vòng lặp retry — chỉ cần khoảng 15 dòng code và sẽ giúp bạn tránh được nhiều đêm trực chiến căng thẳng:
const { Pool } = require('pg');
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
async function connectWithRetry(retries = 5, delay = 2000) {
for (let i = 0; i setTimeout(r, delay));
}
}
throw new Error('Could not connect to database after multiple retries');
}
connectWithRetry();
Xác Minh Kết Nối
Trước khi khởi động lại toàn bộ ứng dụng, hãy xác nhận kết nối hoạt động ở cấp độ TCP:
# Kiểm tra kết nối TCP trực tiếp
nc -zv 127.0.0.1 5432
# Kết quả mong đợi: Connection to 127.0.0.1 5432 port [tcp/postgresql] succeeded!
# PostgreSQL: kiểm tra đăng nhập
psql -h 127.0.0.1 -p 5432 -U myuser -d mydb -c 'SELECT 1;'
# MySQL:
mysql -h 127.0.0.1 -P 3306 -u myuser -p mydb -e 'SELECT 1;'
# Redis:
redis-cli -h 127.0.0.1 -p 6379 ping
# Kết quả mong đợi: PONG
Tham Khảo Nhanh Theo Port
5432— PostgreSQL:sudo systemctl start postgresql3306— MySQL/MariaDB:sudo systemctl start mysql6379— Redis:sudo systemctl start redis27017— MongoDB:sudo systemctl start mongod
Mẹo Hữu Ích
Đang làm việc với container hoặc cấu hình mạng tùy chỉnh? Subnet Calculator trên ToolCraft cho phép bạn kiểm tra dải CIDR và xác nhận rằng IP của container nằm trong mạng đúng. Chạy hoàn toàn trên trình duyệt — không tải lên bất cứ dữ liệu nào.

