目录

Docker 报错 driver failed programming external connectivity

这个报错到底在说什么

driver failed programming external connectivity 是 Docker 在给容器配置端口映射时失败抛出的错误。

完整报错通常长这样:

docker: Error response from daemon: driver failed programming external connectivity on endpoint xxx: Bind for 0.0.0.0:8080 failed: port is already allocated

说白了,Docker 想把宿主机的某个端口转发给容器,但这一步没成功。

原因集中在两块:端口被别人占了,或者 Docker 依赖的 iptables 规则乱了。

下面分情况说。

原因一:端口已经被占用

报错末尾带 port is already allocated 或 address already in use,基本就是端口冲突。

先查一下谁占着这个端口:

## 查看 8080 端口被哪个进程占用 lsof -i :8080 ## 没装 lsof 的话用这个 netstat -tunlp | grep 8080

找到占用进程后,要么把它停掉,要么给容器换一个宿主机端口。

换端口最省事:

## 把宿主机端口从 8080 改成 8081
docker run -p 8081:80 nginx

有个容易踩的坑:上一个同名容器没真正退出,端口还攥在它手里。

这时候 docker ps -a 看一眼有没有残留容器,有就先删掉。

原因二:iptables 规则失效

这是最常见、也最容易被忽略的一种。

Docker 靠 iptables 做端口转发。

如果手动重启过 firewalld、iptables 服务,或者改过防火墙规则,Docker 的转发链可能就被清掉了。

表现是:端口没被占用,但容器就是起不来,报的还是 driver failed。

修复办法是重启 Docker,让它重新写入 iptables 规则:

## 正确的重启命令,注意 restart 在前,docker 在后
systemctl restart docker

这里要纠正一个网上流传很广的错误写法。

很多帖子写成 systemctl docker restart,这个顺序是错的,根本执行不了。

systemctl 的语法是 systemctl 动作 服务名,所以必须是 systemctl restart docker。

原因三:firewalld 和 Docker 打架

CentOS 7/8、部分 Rocky Linux 环境里,firewalld 重载后会清空 Docker 创建的 iptables 链。

典型场景:先 firewall-cmd --reload,紧接着新容器就报 driver failed。

短期方案是重启 Docker 重建规则。

长期方案是调整启动顺序,让 firewalld 先起、Docker 后起,或者在 Docker 的配置里关掉 iptables 托管(生产环境慎用,会影响网络隔离)。

原因四:docker0 网桥异常

少数情况下,宿主机的 docker0 网桥状态不对,也会导致这个报错。

可以确认一下网桥还在不在:

## 查看 docker0 网桥信息
ip addr show docker0

网桥丢了或者 IP 段冲突,重启 Docker 一般能恢复。

实在不行就重建网络:

## 谨慎使用,会断开所有自定义网络
docker network prune

排查顺序建议

遇到这个报错,按下面顺序走效率最高,不用挨个试:

  1. 看报错末尾有没有 port is already allocated,有就先排端口占用
  2. 端口没占用,直接 systemctl restart docker,七成情况能解决
  3. 重启后还报错,检查 firewalld 是否刚 reload 过
  4. 以上都不是,再看 docker0 网桥

数据上,端口占用和 iptables 失效这两类加起来,能覆盖绝大多数现场情况。

关键命令一览

目的 命令
查端口占用 lsof -i :端口号
查残留容器 docker ps -a
重启 Docker systemctl restart docker
查看网桥 ip addr show docker0
清理网络 docker network prune

常见问题

Q1. 为什么重启 Docker 就能解决这个报错?

因为 Docker 启动时会重新写入 iptables 转发规则。

很多时候规则是被防火墙重载或人工操作清掉的,重启 Docker 等于把规则补回来。

Q2. systemctl docker restart 为什么没反应?

这个命令的单词顺序错了。

systemctl 的正确语法是 systemctl restart docker,动作在前、服务名在后,写反了系统识别不了。

Q3. 端口没被占用也报这个错,怎么办?

大概率是 iptables 规则失效。

先执行 systemctl restart docker,如果是 firewalld 重载导致的,重启后立刻就好了。

Q4. 怎么彻底避免 firewalld 和 Docker 冲突?

调整服务启动顺序,让 firewalld 先于 Docker 启动。

每次手动改完防火墙规则后,记得补一次 systemctl restart docker,让 Docker 重新接管自己的转发链。

写在最后

这个报错看着唬人,其实九成是端口占用或 iptables 失效两件事。

排查别上来就重装 Docker,先按端口、防火墙、网桥的顺序过一遍,基本都能定位到。

需要提醒的是,本文给的方案在常见 Linux 发行版上验证过,但不同版本的 firewalld 行为略有差异,具体以你环境的实际报错为准。

如果大家按这套流程还是没搞定,或者遇到了别的 Docker 网络怪问题,欢迎在评论区贴出完整报错一起看看~~~

版权声明

未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!

本文原文链接: https://fiveyoboy.com/articles/docker-driver-failed-programming-external-connectivity/

备用原文链接: https://blog.fiveyoboy.com/articles/docker-driver-failed-programming-external-connectivity/

🍵 若本篇文章帮到了你

不必多,一杯茶的心意,就是我继续写作的动力 🌿

微信 / 支付宝收款码