TL;DR: Your host firewall is fighting docker over iptables. The reliable fix is letting docker manage iptables: stop the conflicting firewall or set the firewall's docker zone correctly, then restart docker. On firewalld systems, the cleanest path is keeping firewalld running and restarting docker after it, so docker inserts its rules into the right chains.

## The error

```text
Error response from daemon: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i br0 -j RETURN: iptables: No chain/target/match by that name.)
```

## Fix it

1. Check what manages the firewall:
   `sudo systemctl status firewalld ufw 2>/dev/null`
   Expected: one of them active.
2. With firewalld: restart docker AFTER firewalld so rules land correctly:
   `sudo systemctl restart firewalld && sudo systemctl restart docker`
   Expected: daemon starts, networks work.
3. With ufw: either disable it (`sudo ufw disable`) or add the standard docker bypass rules, then restart docker.
4. Verify:
   `docker run --rm -p 8080:80 nginx:alpine`
   Expected: starts without iptables errors.

## When this applies
- Daemon fails to start or networks fail right after firewall changes
- RHEL/CentOS/Fedora with firewalld, Ubuntu with ufw

## When this does NOT apply
- Port bind conflicts (userland proxy errors, different fix)
- `"iptables": false` already set in daemon.json (then docker is not supposed to touch iptables; check your own rules)

## Versions
All Docker Engine versions on Linux with an active firewall manager.

## Why it happens
Docker programs NAT and filter rules in iptables at daemon start and per network. If firewalld rewrites the chains afterward, or ufw's default policies drop docker's chains, the daemon's rule inserts fail and network setup aborts.

## Edge cases
- Setting `"iptables": false` in daemon.json stops docker from managing rules, but then YOU own all NAT/port-forwarding; containers lose published-port connectivity unless you add rules manually.
- Docker Desktop for Mac/Windows does not use host iptables; this is Linux-only.
- Custom `--iptables=false` plus userland-proxy disabled equals no published ports at all; keep at least one path working.
