Linux 中 Docker 启动服务时报错 driver failed programming external connectivity on endpoint: xxxx

环境: Rocky 8.6 (CentOS 7)、firewalldDocker

PS: 如果防火墙关闭的话,或许一直都不会遇到该问题吧,又掉了一撮头发。

当且仅当需要占用服务器的端口时才会报错,如果不需要映射端口,也不会遇到相应的问题
比如: docker run -d --name nginx-test1 nginx 这种的没有映射端口
docker run -d --name nginx-test1 -p 80:80 nginx 映射端口了,就需要操作防火墙(若开启)。

1. 场景

因为服务器上的一个服务需要暴露端口,所以对防火墙进行过操作,并重启了防火墙;然后导致 Docker 上跑的服务都无法正常使用。
当执行 docker run xxxdocker start xxxx 的时候会报下面的错误:

docker: Error response from daemon: driver failed programming external connectivity 
on endpoint xxxx(d3e43fa36d34987312e2c3ffd30d3ce3d1892d43ef951241fc2ae320ffeb1330):  
(iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 9905 -j DNAT 
--to-destination 172.18.0.2:9005 ! -i docker0: iptables: No chain/target/match by that name.
 (exit status 1)).

2. 原因

Dockeriptables 的关系请参考官方文档: https://docs.docker.com/network/iptables/

docker 服务启动的时候,docker 服务会自动向 iptables 注册名为 DOCKER-USERDOCKER 两个链,以便让 docker 服务管理的 容器(containner) 所暴露的端口之间进行通信。

当防火墙 firewalld 重启的时候会导致该链丢失,当使用 docker run 的的时候就会出现上面的报错。

3. 解决方案

3.1 Docker 重启(推荐)

这种方式是最简单粗暴的, 因为 Docker 启动的时候会自动注册。是不是很 nice!!!

systemctl restart docker
# 或
service docker restart 

【注】设置了 --restart=always 参数的容器当 Docker 将会自动启动,如果没有设置就需要手动重启了。
如果想对某个容器设置自动启动,可以通过下面的命令进行设置:

# 更新已有的容器:xxx 为容器的标识或容器的名称
docker container update --restart=always xxxx

# 启动时设置
 docker run -d --name nginx-test1 -p 80:80 --restart=always nginx

3.2 恢复 iptables 规则(不推荐)

这种方式其实就是通过 iptables-save 命令备份防火墙的规则,然后通过 iptables-restore 进行恢复;但是在实践的过程中发现并不是很实用。

  • iptables 中没有 Docker 两个链的时候,那么所有服务所暴露的端口,就不会生效,服务是中断的(这个时候还不如直接重启)。
  • 即使备份了,如果 Docker 暴露服务的有变动,还需要手动去处理差异,也很麻烦。
  • 如果完全没有备份,手动添加对应的链,如果 Docker 运行了很多服务,添加起来也是很费劲的(还是不折腾了)
  • 如果定期备份的话,倒是可以只用这种方式(但是既然服务都已经中断了,还不如直接重启)。

一个 iptables 规则的的复杂度,直接劝退:

# Generated by iptables-save v1.8.4 on Thu Jan 26 14:58:33 2023
*filter
:INPUT ACCEPT [105973064:35160153136]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [96468849:80475545565]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.18.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8805 -j ACCEPT
-A DOCKER -d 172.18.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8801 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Thu Jan 26 14:58:33 2023
# Generated by iptables-save v1.8.4 on Thu Jan 26 14:58:33 2023
*security
:INPUT ACCEPT [105973069:35160156762]
:FORWARD ACCEPT [11122602:8643145221]
:OUTPUT ACCEPT [96468861:80475547136]
COMMIT
# Completed on Thu Jan 26 14:58:33 2023
# Generated by iptables-save v1.8.4 on Thu Jan 26 14:58:33 2023
*raw
:PREROUTING ACCEPT [117095673:43803302209]
:OUTPUT ACCEPT [96468861:80475547136]
COMMIT
# Completed on Thu Jan 26 14:58:33 2023
# Generated by iptables-save v1.8.4 on Thu Jan 26 14:58:33 2023
*mangle
:PREROUTING ACCEPT [117095673:43803302209]
:INPUT ACCEPT [105973071:35160156988]
:FORWARD ACCEPT [11122602:8643145221]
:OUTPUT ACCEPT [96468861:80475547136]
:POSTROUTING ACCEPT [107591469:89118692771]
COMMIT
# Completed on Thu Jan 26 14:58:33 2023
# Generated by iptables-save v1.8.4 on Thu Jan 26 14:58:33 2023
*nat
:PREROUTING ACCEPT [288081:17293388]
:INPUT ACCEPT [287965:17286375]
:POSTROUTING ACCEPT [1756221:105814926]
:OUTPUT ACCEPT [1756221:105814926]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.18.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.18.0.2/32 -d 172.18.0.2/32 -p tcp -m tcp --dport 8805 -j MASQUERADE
-A POSTROUTING -s 172.18.0.3/32 -d 172.18.0.3/32 -p tcp -m tcp --dport 8801 -j MASQUERADE
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8805 -j DNAT --to-destination 172.18.0.2:8805
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8801 -j DNAT --to-destination 172.18.0.3:8801
COMMIT
# Completed on Thu Jan 26 14:58:33 2023

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注