前段时间要部署一个Java项目,项目本身用Docker容器化,需要连接另一台服务器上的Elasticsearch做数据查询。
我心想这有什么难的?容器能访问外网,ES服务也正常运行,配置好地址就行了呗。
结果一部署就傻眼了。
项目启动后,日志里疯狂报错:
Connection refused!连接被拒绝。
我第一反应是网络问题,赶紧进容器里测试一下网络连通性:
用ping
测试外部服务器的IP,结果显示Network is unreachable。
这就奇怪了,容器连基本的网络都不通?
为了排除是不是我理解错了,我在宿主机上测试了一下:
# 在宿主机上ping外部服务器
ping 192.168.1.200
# 正常
# telnet测试ES端口
telnet 192.168.1.200 9200
# 也通
宿主机的网络完全正常,能ping通,能连ES服务。但是Docker容器就是不行。
这说明问题出在Docker的网络配置上。
我开始怀疑是Docker的网络设置有问题。检查了一下Docker网络:
# 查看Docker网络
docker network ls
# 查看默认bridge网络详情
docker network inspect bridge
网络配置看起来都正常,容器也分配到了正确的IP地址。
然后我想起来一个重要的点:Linux的IP转发功能。
cat /proc/sys/net/ipv4/ip_forward
结果显示是0!
这下我明白了:IP转发功能被禁用了。
Docker的bridge网络需要Linux主机启用IP转发功能,才能让容器访问外部网络。简单来说就是:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
执行完这个命令,再进容器测试网络,立马就通了!
Java项目也能正常连接ES了。
上面的方法只是临时生效,重启后又会恢复。要让IP转发永久生效:
# 编辑系统配置
sudo vim /etc/sysctl.conf
# 添加这一行
net.ipv4.ip_forward=1
# 让配置生效
sudo sysctl -p
这样重启后IP转发功能也会自动启用。
解决了主要问题后,我又发现了个奇怪的现象。
明明宿主机能正常telnet到ES服务:
但是Java应用还是偶尔连不上,报Connection refused。
我在ES服务器上用tcpdump抓了个包:
发现确实有连接请求到达ES服务器,但是被拒绝了。
这就很奇怪了,明明网络是通的,为什么还会被拒绝?
后来我试了个奇怪的操作:进入Java容器,手动ping一下ES服务器的IP。
结果ping完之后,Java应用立马就能连上ES了!
我到现在也没完全搞明白这是为什么,可能是某种网络路由缓存的问题,或者是ARP表需要更新。总之,进容器ping一下外部地址,问题就神奇地解决了。
这次踩坑让我对Docker网络有了更深的认识:
Docker的bridge网络完全依赖Linux的IP转发功能。如果IP转发被禁用,容器就变成了孤岛,只能内部通信,无法访问外网。
Docker容器的网络和宿主机网络虽然相通,但有时候路由表或ARP缓存可能不同步,导致一些奇怪的连通性问题。
遇到Docker网络问题,排查顺序应该是:
现在我每次搭建新的Docker环境,都会先检查IP转发设置:
# 检查IP转发状态
cat /proc/sys/net/ipv4/ip_forward
# 如果是0,立马启用
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
# 1. 检查容器网络配置
docker network inspect bridge
# 2. 进容器测试基础连通性
docker exec -it container_name ping 8.8.8.8
# 3. 检查宿主机IP转发
cat /proc/sys/net/ipv4/ip_forward
# 4. 查看iptables规则
sudo iptables -L -n -v
如果遇到网络时通时不通的奇怪问题,可以试试进容器手动ping一下目标地址。虽然原理我没完全搞明白,但确实有时候管用。
Docker网络看起来简单,实际上涉及很多Linux网络的底层机制。IP转发、iptables、虚拟网桥这些概念,平时不太关注,但是一出问题就很要命。
特别是在生产环境,网络不通直接影响业务。所以Docker网络配置这块,还是要多了解一些原理,出问题的时候才能快速定位。
建议:如果你也在用Docker部署应用,记得检查一下IP转发设置,这是个很基础但很关键的配置!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。