Docker 容器端口转发失效
今天公司 Docker 里的服务突然莫名其妙访问不了了,经过将近一个小时的排查,最后摸索出了问题所在。详细情况是这样的,本来 Docker 里有个 web 服务,80
端口映射到宿主 0.0.0.0:18800
,最初一切都很顺利,从前天开始会突然无法从外部网络访问服务,刚开始重启容器后问题的确消失了,但后来问题出现越来越频繁,最后到今天重启也无法解决问题。
下面详细记录下我排查问题的经过。
1. 从外部排查
首先从外部查起,打开浏览器看报错代码,chrome 报错显示 no response
服务器无响应,一脸懵逼明明网络是正常的,我的电脑和服务器在两个互通的内网下,能够 ping 通服务器,ssh 也正常。然后 curl -vvv
也证实了同样的结果——服务器完全不响应请求,没有发回任何数据。看样子问题出在服务端,从内部排查比较靠谱。
2. 进入容器,从内部排查
是不是服务挂了?登入服务器,进入容器内部排查问题,docker exec -it container /bin/bash
进入容器环境查看,发现服务后端进程正常运行,容器内 curl -vvv localhost
输出结果也正常,服务日志没有异常记录,但是仔细看完全没有刚刚从我电脑上请求的记录,也就是说容器里后端是正常的,只是没有收到外部请求。这让我更加疑惑了,既然容器内服务本身没问题,问题是不是在宿主服务器上?
3. 退一步海阔天空?
那么现在查查看服务器本身有没有问题。
docker ps
查看容器的配置,那个容器的端口映射配置显示0.0.0.0:18800->80/tcp
,正常无误;netstat -apn | grep -w 18800
显示 docker proxy 也在正常监听;ifconfig
、ip addr
…… 各种查看日志也没有发现服务器网络配置有异常变动;tcpdump port 18800
在宿主服务器监听数据包来往的大体情况,然后从我的电脑发起请求。还是很奇怪,能看到发起请求的数据包正常到达端口18800
,后端服务就是没有任何回应;iptables --list-rules
,服务器环境比较复杂,iptables
规则很多也很复杂,iptables -L FORWARD
大体阅读了下FORWARD
链,也都正常的,不存在意外REJECT
、DROP
的情况;
这让我太疑惑了,现在既然连转发查下来都是正常的,问题到底处在哪一环???
4. 我有一个大胆的想法系列!
我有一个大胆的想法,问题还是出在宿主服务器转发一环上!我也不知道为什么!有一个比较奇怪的现象是,从宿主服务器 curl localhost:18800
也能得到正常的响应,但从网络中其他电脑发请求就是不行,说明 docker 端口转发设置其实也是正常生效的。
因为服务器的 iptables
规则超级多,我并没有全部读完,所以我决定大胆尝试(作死)一波
iptables -P FORWARD ACCEPT
。FORWARD
链的 policy 本来是DROP
,我先来把它改成ACCEPT
,尝试发现没用,继续;iptables -I FORWARD -j ACCEPT
。暴力ACCEPT
FORWARD
链,抱着很大希望,尝试结果还是失败;iptables -I INPUT -j ACCEPT
、iptables -I OUTPUT -j ACCEPT
,意料之中的失败;
所以问题到底出在哪里???(趁人不注意乖乖把 iptables
恢复原样)回回神仔细考虑分析了下,的确只剩下上面这种可能了,问题只能出在宿主转发上!🤔再次一脸懵逼之余漫无目的地随手敲打敲打键盘 sysctl net/ipv4/ip_forward
…… 等一下!它输出了:net.ipv4.ip_forward = 0
?!内核转发为什么是关闭的?!赶紧 sysctl net/ipv4/ip_forward=1
再尝试,我的想法果然是对的,还是宿主转发的问题,现在可以正常访问了!
我靠!瞎搞半天,最后问题居然不在 docker 上,🙄查看下 /etc
里 sysctl
的配置文件,居然把内核转发给关了!服务器谁写的坑爹配置!我现在很好奇以前是怎么用的…… 是不是写死进哪个脚本里去了?不管了,只要现在能稳定用就好。