Cách sửa lỗi 'getaddrinfo ENOTFOUND' trong Node.js: Hướng dẫn thực tế

intermediate🌐 Networking2026-05-25| Node.js (v14+), Linux (Ubuntu/Debian), macOS, Docker Container

Error Message

Error: getaddrinfo ENOTFOUND api.example.com
#nodejs#dns#mạng#getaddrinfo#docker

Khi ứng dụng của bạn không tìm thấy đích đếnỨng dụng Node.js của bạn đang hoạt động mượt mà cho đến khi đột ngột gặp phải một bức tường gạch. Nhật ký (logs) của bạn tràn ngập lỗi mạng trông giống như một mớ hỗn độn ngôn ngữ máy tính:

Error: getaddrinfo ENOTFOUND api.example.com
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:107:26)

Nói một cách dễ hiểu, getaddrinfo ENOTFOUND có nghĩa là Node.js đã yêu cầu hệ điều hành cung cấp địa chỉ IP, và hệ điều hành trả lời: "Tôi không biết đó là cái gì." Đây không phải là lỗi máy chủ như 404. Đó là vấn đề "Bạn ở đâu?" xảy ra trước khi một byte dữ liệu nào đó được gửi đi.

Tại sao điều này lại xảy ra?Phân giải DNS là danh bạ điện thoại của Internet. Lỗi này được kích hoạt khi việc tra cứu thất bại ở lớp mạng. Vì Node.js sử dụng thread pool để xử lý các lệnh gọi hệ thống này thông qua libuv, lỗi ở đây thường chỉ ra vấn đề về môi trường hơn là lỗi trong logic JavaScript của bạn.

Quy trình gỡ lỗi: Tìm nguyên nhân gốc rễTrước khi bạn bắt đầu cấu trúc lại mã nguồn (refactoring), bạn cần cô lập nơi xảy ra sự cố. Đó là do mã code, container, hay chính mạng lưới?

1. Bắt đầu với bài kiểm tra "Đã cắm điện chưa?"Tất cả chúng ta đều đã từng gặp tình huống này: nhìn chằm chằm vào màn hình suốt 45 phút chỉ để nhận ra có một lỗi đánh máy trong tệp .env. Hãy kiểm tra hostname của bạn ngay lập tức. Tôi đã từng mất hai giờ đồng hồ để truy tìm nguyên nhân một vụ sập hệ thống production chỉ vì cấu hình ghi api.exampel.com thay vì example.com. Hãy chạy một bài kiểm tra nhanh 5 giây từ terminal của bạn:

ping api.example.com
# HOẶC
nslookup api.example.com

Nếu các lệnh này trả về "Host not found" hoặc "NXDOMAIN," vấn đề không nằm ở Node.js. Cài đặt DNS của máy bạn hoặc nhà cung cấp dịch vụ Internet (ISP) có khả năng là thủ phạm.

2. Kiểm tra các biến môi trườngCác ứng dụng hiện đại phụ thuộc rất nhiều vào process.env. Nếu bạn sử dụng dotenv, hãy đảm bảo nó được tải trước khi thực hiện các lệnh gọi mạng. Một sai lầm phổ biến là cố gắng truy cập một URL đang bị undefined vì biến môi trường chưa được tải. Điều này dẫn đến việc Node.js cố gắng phân giải chuỗi ký tự "undefined," và tất nhiên là thất bại.

// Thêm một bước kiểm tra nhanh
if (!process.env.API_HOST) {
  throw new Error("CRITICAL: API_HOST environment variable is missing!");
}
console.log("Connecting to:", process.env.API_HOST);

3. Giải mã bí ẩn DockerBên trong một Docker container, localhost trỏ đến chính container đó, không phải máy tính của bạn. Nếu API của bạn nằm trong một container khác, hãy sử dụng tên dịch vụ (service name) từ tệp docker-compose.yml của bạn. Ví dụ: nếu dịch vụ cơ sở dữ liệu của bạn được đặt tên là db-server, chuỗi kết nối của bạn nên sử dụng db-server, thay vì một địa chỉ IP có thể thay đổi mỗi khi bạn khởi động lại hệ thống.

Các giải pháp thực tế### Tách biệt giao thức khỏi HostnameCác module Node.js cấp thấp như http.request rất khắt khe. Chúng yêu cầu hostnamepath phải tách biệt. Nếu bạn vô tình truyền https://api.example.com vào trường hostname, hệ điều hành sẽ cố gắng tìm một máy chủ có tên chính xác là "https://..." và thất bại với lỗi ENOTFOUND.

const http = require('http');

const options = {
  hostname: 'api.example.com', // Chỉ hostname sạch
  port: 80,
  path: '/v1/users',
  method: 'GET'
};

const req = http.request(options, (res) => {
  console.log(`Status: ${res.statusCode}`);
});

req.on('error', (e) => {
  console.error(`Lỗi mạng: ${e.message}`);
});

req.end();

Xử lý Proxy trong doanh nghiệpTrong nhiều văn phòng, bạn không thể truy cập thế giới bên ngoài nếu không có proxy như Squid hoặc Blue Coat. Node.js không phải lúc nào cũng tự động phát hiện ra chúng. Bạn có thể cần một package như https-proxy-agent để định tuyến lưu thông chính xác qua cổng nội bộ của mình (ví dụ: 10.0.0.1:8080).

const { HttpsProxyAgent } = require('https-proxy-agent');
const axios = require('axios');

const agent = new HttpsProxyAgent('http://10.0.0.1:8080');
axios.get('https://api.external.com', { httpsAgent: agent })
  .then(res => console.log("Thành công!"))
  .catch(err => console.error("Lỗi Proxy:", err.message));

Các bước xác minhSau khi bạn đã áp dụng bản sửa lỗi, hãy xác minh một cách có hệ thống để đảm bảo nó hoạt động ổn định:

  • Xóa bộ nhớ đệm DNS (Flush DNS Cache): Trên macOS, chạy sudo killall -HUP mDNSResponder. Trên Windows, sử dụng ipconfig /flushdns. Điều này đảm bảo bạn không nhìn thấy các bản ghi cũ bị hỏng.- Kiểm tra với cURL: Chạy curl -I https://api.example.com. Nếu cURL kết nối được nhưng Node.js thì không, vấn đề có lẽ nằm ở phiên bản Node.js của bạn hoặc cấu hình của một thư viện cụ thể.- Triển khai DNS Caching: Theo mặc định, Node.js thực hiện một lần tra cứu mới cho mỗi yêu cầu. Dưới tải trọng lớn hơn 1.000 yêu cầu mỗi giây, điều này có thể làm quá tải trình phân giải DNS của bạn. Hãy sử dụng một package như dnscache để lưu lại kết quả và giảm độ trễ từ 10-20ms cho mỗi yêu cầu.## Phòng ngừa và các phương pháp tốt nhấtĐể giữ ENOTFOUND khỏi môi trường production của bạn, hãy tuân thủ các quy tắc sau:
  • Trình phân giải dự phòng (Fallback Resolvers): Cấu hình tệp /etc/resolv.conf của máy chủ để sử dụng Google (8.8.8.8) hoặc Cloudflare (1.1.1.1) nếu nhà cung cấp địa phương của bạn hoạt động không ổn định.- Lập kế hoạch mạng thông minh: Tránh các khối CIDR bị chồng lấn khi thiết lập microservices. Tôi sử dụng Subnet Calculator trên ToolCraft để kiểm tra lại các phép tính mạng của mình. Nó giúp đảm bảo các cổng gateway và dải IP nội bộ không xung đột trước khi tôi triển khai lên AWS hoặc Azure.- Xử lý lỗi mạnh mẽ: Đừng bao giờ để một lệnh gọi mạng "trần trụi". Hãy bao bọc chúng trong các khối try/catch. Lỗi ENOTFOUND nên kích hoạt chiến lược thử lại (retry strategy) hoặc thông báo nhẹ nhàng cho người dùng, chứ không phải làm sập hoàn toàn ứng dụng.## Bài học rút raLỗi getaddrinfo ENOTFOUND hiếm khi là lỗi trong mã nguồn của bạn. Nó thường là tín hiệu cho thấy môi trường của bạn — hệ điều hành, mạng Docker hoặc các tệp cấu hình — đang bị mất đồng bộ. Bằng cách xác minh hostname, kiểm tra việc tải môi trường và hiểu cách các container giao tiếp với nhau, bạn có thể giải quyết các lỗi này và quay lại xây dựng các tính năng.

Related Error Notes