服务器重启后Docker服务访问失败

问题描述:

Docker运行的web服务正常运行,配置服务器重启自启动Docker和容器。但是机房断电重启后,web服务无法正常访问。telnet服务器的端口不通。

环境:

ApplicationVersion
OScentos7
Docker19.03.1
docker-compose1.24.0

一、 检查服务容器是否启动

$ docker-compose ps

在这里插入图片描述

发现web服务器与php容器都已正常启动

如果有容器未启动就启动容器
$ docker-composer up -d 

重启后,访问web服务是否正常,服务启动可能会需要一些时间,一般能telnet通端口基本就不会有什么问题。

二、检查是否被防火墙屏蔽

服务容器正常启动依然无法访问,就需要检查一下防火墙了,先查看防火墙状态

$ firewall-cmd --state

在这里插入图片描述
not running发现防火墙未运行,可以排除防火墙的影响

如果是running则需要进一步排查,端口是否开放

firewall-cmd --list-ports
firewall-cmd --list-services
如果端口未开放,有两种情况:
1. 不需要防火墙,直接关掉防火墙服务
$ sudo systemctl stop firewalld.service
2. 需要防火墙,添加需要开放的端口
$ sudo firewall-cmd --add-port=80/tcp --permanent
$ firewall-cmd --reload

完成后访问web服务看是否正常

三、检查路由IP转发是否开启

前两步的影响排出后,最后检查IP转发是否开启,一般问题出在这里

$ sysctl net.ipv4.ip_forward

在这里插入图片描述

发现IP转发未开启,解决方案:
开启IP转发,在配置文件添加策略
$ echo 'net.ipv4.ip_forward = 1' | sudo tee -a /usr/lib/sysctl.d/50-default.conf

重新加载配置文件(也可以重启network服务)

$ sudo sysctl -p /usr/lib/sysctl.d/50-default.conf

查看IP转发是否开启
在这里插入图片描述
IP转发已开启,访问web服务看是否正常了。

问题解析:

Docker与宿主机的端口映射是通过iptables实现的,容器启动时会在iptables中添加DOCKER链和nDNAT规则

简单来了解一下,查看一下nat表的DOCKER

$ sudo iptables -t nat -nvL DOCKER

在这里插入图片描述

从图中可以看到有两条DNAT规则,这两条规则分别将宿主机44380端口的报文转发到172.17.3.244380端口上,而172.17.3.2是分配给nginx容器的ip(可以通过docker inspect 容器ID命令查看)

而这个DNAT规则需要宿主机开启内核IP转发功能,所以IP转发未开启会导致服务访问失败。

问题的根源找到了,但是产生的原因还没找到。

为什么之前没有手动开启IP转发时DOCKER服务依然能正常运行?

这是因为Docker daemon启动时会检查IP_FORWARD是否开启,如果未开启则临时开启,因为是临时开启所以在network服务重启后就会失效。服务器断电重启后network服务自然会重启,就有可能导致IP_FORWARD失效。一般docker服务正常运行一段时间后却突然访问不了,大不多是因此引起的,可以从这里开始排查。

当然不妨自己来做个试验

  1. 关闭IP转发功能,此时访问web服务失败
  2. 重启docker
$ sudo systemctl restart docker

访问web服务成功,查看IP转发功能是已开启状态。所以docker服务访问失败时往往能够通过重启docker解决,但是不推荐这么做,因为既没真正解决问题容器重启还比较费时。

  1. 重启network
$ sudo systemctl restart network

访问web服务成功,查看IP转发功能是已关闭状态

最后记得将IP转发功能恢复

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐