Sửa lỗi 'iptables: No chain/target/match by that name' Khi Khởi Động Docker Container Sau Khi Restart Hệ Thống

intermediate🐳 Docker2026-05-16| Linux (Ubuntu 20.04/22.04, Debian, CentOS/RHEL), Docker Engine 20.x+, systemd

Error Message

Error response from daemon: driver failed programming external connectivity on endpoint mycontainer: iptables: No chain/target/match by that name.
#docker#iptables#mạng#linux#systemd

Lỗi

Bạn khởi động lại server, đưa các container trở lại, rồi gặp phải lỗi này:

Error response from daemon: driver failed programming external connectivity on endpoint mycontainer: iptables: No chain/target/match by that name.

Mọi thứ vẫn hoạt động tốt trước khi reboot. Các container không thay đổi gì. Vậy mà Docker từ chối khởi động chúng. Thật bực bội vì nhìn bề ngoài không có gì có vẻ bị hỏng cả.

Chuyện gì thực sự đang xảy ra

Docker quản lý mạng container bằng cách chèn các rule vào iptables — cụ thể là vào các chain như DOCKER, DOCKER-USERDOCKER-ISOLATION-STAGE-1. Docker tạo ra các chain này khi daemon khởi động.

Sau khi reboot, nếu có gì đó tải lại hoặc reset các rule firewall sau khi Docker đã khởi động, các chain đó sẽ bị xóa sạch. Các rule của Docker biến mất, nhưng Docker không biết điều đó. Khi khởi động container, Docker cố gắng thêm rule vào các chain không còn tồn tại — đó là lý do xuất hiện "No chain/target/match by that name."

Các nguyên nhân thường gặp:

  • firewalld hoặc ufw tải lại sau khi Docker khởi động và flush iptables
  • Một script iptables -F hoặc iptables --flush tùy chỉnh chạy lúc boot
  • Race condition trong thứ tự systemd: Docker khởi động trước khi firewall sẵn sàng, sau đó firewall reset mọi thứ
  • Chuyển đổi giữa iptables-legacyiptables-nft — rất phổ biến trên Debian/Ubuntu 20.04 trở lên

Fix 1: Khởi động lại Docker Daemon (Sửa nhanh)

Cách khôi phục nhanh nhất ngay lúc này: restart Docker. Điều này buộc Docker phải tạo lại các chain iptables từ đầu.

sudo systemctl restart docker

Sau đó khởi động container của bạn:

docker start mycontainer
# hoặc
docker compose up -d

Hoạt động ngay trong hầu hết các trường hợp. Nhưng lỗi sẽ quay lại ở lần reboot tiếp theo nếu nguyên nhân gốc rễ chưa được giải quyết — vì vậy hãy đọc tiếp.

Fix 2: Kiểm tra Backend iptables (Ubuntu/Debian)

Trên Ubuntu 20.04 trở lên và Debian 10 trở lên, hệ thống có thể đang dùng iptables-nft (backend nftables) trong khi Docker mong đợi iptables-legacy. Khi chúng không khớp, việc tra cứu chain thất bại âm thầm trong quá trình khởi động Docker.

Kiểm tra backend nào đang hoạt động:

sudo update-alternatives --display iptables

Nếu kết quả hiển thị iptables-nft là lựa chọn hiện tại, hãy chuyển sang legacy:

sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy

Khởi động lại Docker:

sudo systemctl restart docker

Chỉ riêng bước này đã giải quyết được lỗi trên phần lớn các máy Debian/Ubuntu hiện đại. Hãy thử cách này trước tiên trên những hệ thống đó.

Fix 3: Sửa Thứ tự Service systemd (firewalld)

Bạn đang chạy firewalld? Đó có thể là thủ phạm. Firewalld tải lại bộ rule của chính nó trong quá trình boot — và nếu việc tải lại đó xảy ra sau khi Docker đã thiết lập xong các chain, firewalld sẽ xóa sạch chúng.

Xác nhận firewalld đang hoạt động:

sudo systemctl status firewalld
sudo firewall-cmd --list-all

Yêu cầu systemd Docker phải chờ firewalld khởi động xong trước khi bắt đầu:

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/after-firewalld.conf <<EOF
[Unit]
After=firewalld.service
EOF

Áp dụng thay đổi:

sudo systemctl daemon-reload
sudo systemctl restart docker

Trên các dev server mà bạn thực sự không cần firewalld, chỉ cần tắt nó đi:

sudo systemctl disable --now firewalld

Fix 4: Ngăn Script Flush iptables Chạy Sau Docker

Bạn có script tùy chỉnh flush các rule iptables — chẳng hạn trong /etc/rc.local hoặc một systemd unit riêng? Hãy kiểm tra thời điểm chạy của nó so với Docker khi boot.

Flush toàn bộ chain thủ công, rồi để Docker tự xây dựng lại:

# Xóa toàn bộ rule iptables
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t mangle -F
sudo iptables -t mangle -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT

# Xây dựng lại các chain của Docker
sudo systemctl restart docker

Cần giữ lại script flush? Thêm lệnh systemctl restart docker vào cuối script đó. Hoặc cấu hình thứ tự systemd để Docker luôn khởi động sau cùng.

Kiểm tra

Sau khi áp dụng fix, xác nhận các chain của Docker tồn tại:

sudo iptables -L DOCKER --line-numbers

Bạn sẽ thấy kết quả tương tự như sau:

Chain DOCKER (1 references)
num  target     prot opt source               destination

Nếu vẫn thấy iptables: No chain/target/match by that name ở đây, có nghĩa là các chain của Docker vẫn chưa được tạo. Hãy restart daemon và kiểm tra lại.

Xác nhận container khởi động bình thường:

docker start mycontainer
docker ps  # container phải hiển thị trạng thái Up

Thực hiện reboot toàn bộ để xác nhận fix hoạt động bền vững:

sudo reboot
# Sau khi kết nối lại:
docker ps -a              # kiểm tra trạng thái container
journalctl -u docker -n 50  # xem log Docker để tìm lỗi

Phòng ngừa

Một vài điều đáng thiết lập để vấn đề này không tái diễn:

  • Cố định backend iptables. Chuyển sang iptables-legacy sẽ được giữ nguyên qua các lần reboot — nhưng hãy kiểm tra lại sau các lần nâng cấp OS lớn. Lệnh apt upgrade trên Ubuntu có thể âm thầm đổi lại thành nft.
  • Chỉ dùng --iptables=false khi bạn biết mình đang làm gì. Đặt "iptables": false trong /etc/docker/daemon.json để tự quản lý hoàn toàn — nhưng điều đó có nghĩa là bạn phải tự viết mọi rule NAT và forwarding. Thiếu một rule là container mất kết nối internet.
  • Trực quan hóa thứ tự boot. Chạy systemd-analyze plot > boot.svg và mở file SVG trong trình duyệt. Bạn sẽ thấy chính xác Docker và firewalld khởi động tại thời điểm nào trên timeline — race condition trở nên rõ ràng ngay lập tức.
  • Lên kế hoạch cho các subnet Docker. Khi chạy nhiều mạng Docker với subnet tùy chỉnh, xung đột CIDR với mạng host gây ra một lớp lỗi khác nhưng cũng khó hiểu không kém. Subnet Calculator trên ToolCraft rất tiện để kiểm tra nhanh xem subnet bridge có xung đột với các route hiện có hay không trước khi gán.

Tham Chiếu Nhanh

# Trình tự fix phổ biến nhất:
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
sudo systemctl restart docker

# Xác nhận các chain Docker đã hoạt động:
sudo iptables -L DOCKER

# Kiểm tra log Docker nếu vẫn còn lỗi:
journalctl -u docker -n 100 --no-pager

Related Error Notes