Bắt bệnh Docker: Giải quyết triệt để lỗi "Port is already allocated" khi bind cổng 6379
Chắc hẳn khi làm Backend, không ít lần chúng ta phải dựng môi trường local bằng Docker. Giả sử bố đời đang hì hục gõ docker-compose up -d để kéo con container hasakinow-redis lên phục vụ cho module cache hoặc hàng đợi xử lý đơn hàng hỏa tốc, thì đùng một cái, Terminal ném thẳng dòng log đỏ lòm này vào mặt:
Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint hasakinow-redis... Bind for 0.0.0.0:6379 failed: port is already allocated
Đừng vội hoảng! Nhìn thì dài dòng và nguy hiểm, nhưng thực chất con bug này lại cực kỳ "ngô nghê" và rất dễ giải quyết. Hãy cùng mổ xẻ nguyên nhân và cách "xử tử" nó trong vòng 3 nốt nhạc nhé.
1. Dịch lỗi: Chuyện gì đang xảy ra dưới Local?
Để hiểu lỗi này, chúng ta cần nhớ lại nguyên tắc hoạt động của Docker Port Mapping (Ánh xạ cổng). Trong file docker-compose.yml, khi bạn khai báo:
ports:
- "6379:6379"
Nó có nghĩa là: "Ê Docker, hãy lấy cái cổng 6379 trên máy thật của tôi (Host), nối thông vào cái cổng 6379 bên trong con container Redis nhé."
Dòng thông báo lỗi Bind for 0.0.0.0:6379 failed: port is already allocated đơn giản là lời than vãn của Docker: "Tôi đã cố cắm dây vào cổng 6379 trên máy tính của bạn, nhưng cổng đó đã bị một phần mềm khác chiếm mất rồi (allocated), tôi không cắm vào được nữa!"
2. Truy tìm thủ phạm: Ai đang chiếm cổng 6379?
Cổng 6379 là cổng mặc định của Redis. Việc nó bị chiếm dụng thường rơi vào 2 kịch bản kinh điển sau:
- Kịch bản 1: "Nuôi ong tay áo"
Trước đây bạn (hoặc một đồng nghiệp) đã từng cài trực tiếp Redis-server lên thẳng hệ điều hành gốc (thông qua
apt-get install redistrên Ubuntu hoặcbrew install redistrên Mac) và nó đang chạy ngầm như một Service (Background Daemon). - Kịch bản 2: "Bóng ma Container cũ" Bạn đang chạy một project khác cũng dùng Redis ở cổng 6379 bằng Docker. Hoặc trước đó bạn tắt container không đúng cách (crash), khiến cái cổng vẫn đang bị con container cũ "ngậm" chặt mà chưa nhả ra.
3. Ba tuyệt chiêu giải quyết triệt để
Tùy vào tình huống, bố đời có thể áp dụng 1 trong 3 cách sau để thông chốt.
Tuyệt chiêu 1: Bắt tận tay, day tận trán (Kill process)
Chúng ta sẽ tìm xem tiến trình nào đang chiếm cổng và "trảm" nó. Mở Terminal lên và gõ:
sudo lsof -i :6379
# Hoặc
sudo netstat -tulpn | grep 6379
Màn hình sẽ in ra tên tiến trình (PID) đang giữ cổng này.
- Nếu nó là
redis-serverchạy ngầm của hệ điều hành, hãy tắt nó đi:sudo systemctl stop redis. - Nếu không biết nó là gì, cứ dùng lệnh kill thẳng tay bằng mã PID (ví dụ PID là 1234):
sudo kill -9 1234.
Tuyệt chiêu 2: Quét dọn tàn dư Docker
Nếu nghi ngờ có container cũ đang chạy, hãy kiểm tra danh sách container:
docker ps
Nếu thấy một con Redis cũ đang sống sờ sờ, hãy tắt nó:
docker stop <container_id>
Nếu Docker network bị kẹt (lỗi mạng ảo), bạn có thể gõ lệnh này để dọn dẹp các network không còn sử dụng (lưu ý: nó sẽ dọn khá sạch sẽ đấy nhé):
docker network prune
Tuyệt chiêu 3: "Né đòn" (Đổi cổng ánh xạ)
Đây là cách thanh lịch nhất nếu bố đời thực sự CẦN chạy song song 2 dự án cùng dùng Redis trên một máy.
Thay vì bắt máy chủ gốc (Host) phải hy sinh cổng 6379, chúng ta chỉ việc đổi cổng bên ngoài, còn cổng bên trong container vẫn giữ nguyên. Mở file docker-compose.yml lên và sửa lại:
services:
hasakinow-redis:
image: redis:alpine
ports:
- "6380:6379" # Sửa cổng 6379 thành 6380 ở phía Host (bên trái)
Bây giờ, khi ứng dụng Backend (như Laravel hay Go) muốn kết nối vào con Redis này, bạn chỉ cần sửa file .env thành REDIS_PORT=6380. Docker sẽ tự động chuyển luồng traffic từ 6380 bên ngoài vào đúng 6379 bên trong. Chạy 10 dự án cùng lúc cũng không bao giờ sợ đụng hàng!
Lời kết
Lỗi đụng port (Port Allocation) là bài học vỡ lòng cực kỳ quen thuộc đối với bất kỳ ai theo nghiệp Backend và DevOps. Nắm vững được nguyên lý Ánh xạ cổng (Port Mapping) và biết cách dùng các lệnh Linux cơ bản như lsof hay netstat để check port sẽ giúp bố đời tiết kiệm được hàng giờ đồng hồ gãi đầu gãi tai.
Kéo lại con hasakinow-redis lên và tiếp tục chiến đấu thôi! Chúc bố đời code mượt mà và không còn bị Docker "hành" nữa nhé!
All rights reserved