现象

  • 某个同学执行docker启动容器的时候提示
docker: Error response from daemon: driver failed programming external connectivity on endpoint frosty_montalcini (5f23d1b819d9b55a229a9fb789c7f0897123b7e218694eefbc31487e8e4883a6):  (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 8082 -j DNAT --to-destination 172.17.0.5:80 ! -i docker0: iptables: No chain/target/match by that name.
 (exit status 1)).
  • 这个报错Error response from daemon提示是daemon给了一个错误的响应

  • daemon是这个

    [root@qianhanyi ~]# ps -ef|grep dockerd
    root      16921      1  2 04:12 ?        00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
    
    
  • 为何能给response,因为dockerd是个RESTful的API server

    [root@qianhanyi ~]# docker version
    Client: Docker Engine - Community
     Version:           23.0.1
     API version:       1.42  # 这里
    
    # 有空考虑写一个api操作docker的文章
    
  • 报错提到了iptables,这是关键线索

现场还原

以centos7为例

  • 确保你的firewalld正常

    [root@qianhanyi ~]# systemctl status firewalld
    ● firewalld.service - firewalld - dynamic firewall daemon
       Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
       Active: active (running) since Fri 2022-11-18 04:12:19 CST; 7min ago
         Docs: man:firewalld(1)
     Main PID: 16655 (firewalld)
        Tasks: 2
       Memory: 23.6M
       CGroup: /system.slice/firewalld.service
               └─16655 /usr/bin/python2 -Es /usr/sbin/firewalld --nofork --nopid
    
    ...
    Hint: Some lines were ellipsized, use -l to show in full.
    
    
  • 运行一个容器,比如nginx的

    [root@qianhanyi ~]# docker run -itd -p 8082:80 nginx
    253fe5d60b8446612ae76bee9476eeb96b3c294b46a7c87c3c21ffe26dcaa1ec
    [root@qianhanyi ~]# docker ps -a
    CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS         PORTS                                       NAMES
    253fe5d60b84   nginx      "/docker-entrypoint.…"   4 seconds ago    Up 3 seconds   0.0.0.0:8082->80/tcp, :::8082->80/tcp       infallible_pasteur
    
    
  • 浏览器访问ip:8082,可能会无法访问

  • 此时你想到了防火墙的原因

  • 停了吧

    [root@qianhanyi ~]# systemctl stop firewalld
    [root@qianhanyi ~]# systemctl status firewalld
    ● firewalld.service - firewalld - dynamic firewall daemon
       Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
       Active: inactive (dead) since Fri 2022-11-18 04:26:36 CST; 8s ago
         Docs: man:firewalld(1)
      Process: 16655 ExecStart=/usr/sbin/firewalld --nofork --nopid $FIREWALLD_ARGS (code=exited, status=0/SUCCESS)
     Main PID: 16655 (code=exited, status=0/SUCCESS)
    
    ...
    Nov 18 04:26:35 qianhanyi systemd[1]: Stopping firewalld - dynamic firewall daemon...
    Nov 18 04:26:36 qianhanyi systemd[1]: Stopped firewalld - dynamic firewall daemon.
    Hint: Some lines were ellipsized, use -l to show in full.
    
    
  • 此时应该能访问了

  • 过了一会,你又启动了一个容器

    [root@qianhanyi ~]#  docker run -itd -p 8083:80 nginx
    4a7658f1669a76fd990e5757afe8c32d09fee6bf6b6fa55426e2abf0d88f29e0
    docker: Error response from daemon: driver failed programming external connectivity on endpoint gracious_sutherland (0f46051611e83ef3e69c84bc17b2ef4f60ca03fe729020ba8348c2f845f0d26f):  (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 8083 -j DNAT --to-destination 172.17.0.5:80 ! -i docker0: iptables: No chain/target/match by that name.
     (exit status 1)).
    
    
  • 至此复现了问题

解决

  • 此时你只需重启下docker应用程序

    [root@qianhanyi ~]# systemctl restart docker
    
    # 当然你要关注下,你之前启动的其他容器有没有配置--restart=always, 如果没有那些容器记得需要的话启动下
    
  • 再次启动容器

    [root@qianhanyi ~]#  docker run -itd -p 8083:80 nginx
    803cfa1c24b7c1a0934551fa19915c9abee1b22a2ed8a7a86268a9b244c88e7e
    
    

思考

  • docker 是有网络的,容器网络实质上是由 Dokcer 为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作系统的网络环境中独立出来,形成容器自有的网络设备、IP 协议栈、端口套接字、IP 路由表、防火墙等等与网络相关的模块。
  • 本质的原因本文还是没找到
  • docker网络这部分也可以单独拉出来讲一个篇幅