Fix 'iptables: No chain/target/match by that name' When Starting Docker Container After System Restart

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#network#linux#systemd

The Error

You restart your server, bring your containers back up, and get hit with this:

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

Everything was working fine before the reboot. The containers haven't changed. Yet Docker refuses to start them. It's maddening because nothing on the surface looks broken.

What's Actually Happening

Docker manages container networking by injecting rules into iptables โ€” specifically into chains like DOCKER, DOCKER-USER, and DOCKER-ISOLATION-STAGE-1. Docker creates these chains when the daemon starts.

After a reboot, if something reloads or resets the firewall rules after Docker starts, those chains get wiped. Docker's rules are gone, but Docker doesn't know that. Start a container, and Docker tries to append rules to chains that no longer exist โ€” hence "No chain/target/match by that name."

Usual suspects:

  • firewalld or ufw reloading after Docker starts and flushing iptables
  • A custom iptables -F or iptables --flush script running at boot
  • A systemd ordering race: Docker starts before the firewall is ready, firewall then resets everything
  • Switching between iptables-legacy and iptables-nft โ€” very common on Debian/Ubuntu 20.04+

Fix 1: Restart the Docker Daemon (Quick Fix)

Fastest recovery right now: restart Docker. This forces it to recreate its iptables chains from scratch.

sudo systemctl restart docker

Then start your container:

docker start mycontainer
# or
docker compose up -d

Works immediately in most cases. But the error comes back on the next reboot if the root cause isn't addressed โ€” so keep reading.

Fix 2: Check the iptables Backend (Ubuntu/Debian)

On Ubuntu 20.04+ and Debian 10+, the system may be using iptables-nft (nftables backend) while Docker expects iptables-legacy. When they don't match, chain lookups fail silently during Docker startup.

Check which backend is active:

sudo update-alternatives --display iptables

If it shows iptables-nft as the current choice, switch to legacy:

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

Restart Docker:

sudo systemctl restart docker

This alone resolves the error on the majority of modern Debian/Ubuntu machines. Try this before anything else on those systems.

Fix 3: Fix the systemd Service Order (firewalld)

Running firewalld? That's likely your culprit. Firewalld reloads its own ruleset during boot โ€” and if that reload happens after Docker has already set up its chains, firewalld wipes them.

Confirm firewalld is active:

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

Tell systemd Docker must wait for firewalld to finish before starting:

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

Apply the change:

sudo systemctl daemon-reload
sudo systemctl restart docker

On dev servers where you don't actually need firewalld, just turn it off:

sudo systemctl disable --now firewalld

Fix 4: Stop iptables Flush Scripts from Running After Docker

Got a custom script that flushes iptables rules โ€” something in /etc/rc.local or a dedicated systemd unit? Check its boot timing relative to Docker.

Flush all chains manually, then let Docker rebuild:

# Clear all iptables rules
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

# Rebuild Docker's chains
sudo systemctl restart docker

Need to keep the flush script? Add a systemctl restart docker at the end of it. Or wire up the systemd ordering so Docker always starts last.

Verification

After applying a fix, confirm Docker's chains exist:

sudo iptables -L DOCKER --line-numbers

You should see something like:

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

Getting iptables: No chain/target/match by that name here means Docker's chains still aren't up. Restart the daemon and check again.

Verify the container starts cleanly:

docker start mycontainer
docker ps  # should show container as Up

Do a full reboot test to confirm the fix survives:

sudo reboot
# After reconnecting:
docker ps -a              # check container status
journalctl -u docker -n 50  # scan Docker logs for errors

Prevention

A few things worth locking in so this doesn't resurface:

  • Pin the iptables backend. Switching to iptables-legacy sticks across reboots โ€” but double-check after major OS upgrades. apt upgrade on Ubuntu can silently flip it back to nft.
  • Use --iptables=false only if you know what you're doing. Set "iptables": false in /etc/docker/daemon.json to take full control โ€” but that means you own every NAT and forwarding rule manually. One missed rule and containers lose internet access.
  • Visualize your boot order. Run systemd-analyze plot > boot.svg and open the SVG in a browser. You'll see exactly where Docker and firewalld land on the timeline โ€” race conditions become obvious at a glance.
  • Plan your Docker subnets. When running multiple Docker networks with custom subnets, CIDR conflicts with the host network cause a different but equally confusing class of errors. The Subnet Calculator on ToolCraft is handy for quickly checking whether a bridge subnet clashes with existing routes before assigning it.

Quick Reference

# Most common fix sequence:
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
sudo systemctl restart docker

# Verify Docker chains are up:
sudo iptables -L DOCKER

# Check Docker logs if still failing:
journalctl -u docker -n 100 --no-pager

Related Error Notes