🚀 实战排坑:Docker 容器内连接阿里云 Redis 报 “Host is unreachable” 的终极解决方案

最近在部署 Java 服务时遇到一个非常“坑爹”的问题——容器启动后,应用死活连不上 Redis,一顿排查才发现是 Docker 网络和 Redis 内网网段冲突导致的。
本文详细记录了整个排查与解决的过程,希望能帮到你。


🧩 一、问题背景

环境信息:

  • 系统: CentOS(宿主机)
  • 运行环境: Docker 容器
  • 应用: Java(使用 Netty 连接 Redis)
  • Redis: 阿里云 Redis 内网地址 172.18.3.177:6379

问题现象:

容器内报错如下 👇

Caused by: io.netty.channel.AbstractChannel$AnnotatedNoRouteToHostException: Host is unreachable: r-uf6i6m3hi5qtxpw1ed.redis.rds.aliyuncs.com/172.18.3.177:6379
Caused by: java.net.NoRouteToHostException: Host is unreachable

翻译过来就是 —— “主机不可达”
一开始还以为是安全组或者端口问题,结果完全不是那回事。


🔍 二、深入排查:原来是 Docker 的锅!

进入容器后执行网络相关命令:

ip route

结果发现:

172.18.0.0/16 dev eth0  proto kernel  scope link  src 172.18.0.2

再执行:

docker network inspect bridge

输出片段:

"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"

到这里一切真相大白 👇

Docker 默认创建的 bridge 网络使用的网段是 172.18.0.0/16
而阿里云 Redis 的内网地址刚好也是 172.18.x.x

这就导致容器以为 Redis 在“本地局域网”,不会走宿主机的网关去访问外部。
于是访问 172.18.3.177 时,数据包被路由到了 Docker 内部虚拟网桥,直接丢失


🧭 三、验证过程

容器内执行:

ping r-uf6i6m3hi5qtxpw1ed.redis.rds.aliyuncs.com
nc -vz r-uf6i6m3hi5qtxpw1ed.redis.rds.aliyuncs.com 6379

输出:

connect to 172.18.3.177 port 6379 (tcp) failed: No route to host

完美复现!可以确定是 路由冲突 导致无法访问。


✅ 四、解决方案汇总

下面提供三种解决方案,根据实际场景选择。


🚀 方案一:修改 Docker 默认网段(推荐)

最彻底、最优雅的方式。

1️⃣ 编辑 Docker 配置

sudo vim /etc/docker/daemon.json

添加或修改如下内容:

{
  "bip": "172.31.0.1/16"
}

bip 表示 Docker 默认 bridge 网络的网关。
你可以改成任意不冲突的私有网段,例如:

  • 172.31.0.1/16
  • 192.168.250.1/24
  • 10.200.0.1/16

2️⃣ 重启 Docker 服务

sudo systemctl restart docker

⚠️ 注意:这会删除并重建默认的 bridge 网络,运行中的容器会断网,请提前停止。

3️⃣ 验证是否修改成功

docker network inspect bridge

确认 "Subnet" 已变为新的网段。

重新启动你的容器后,Java 服务即可成功连接 Redis 🎉


🧱 方案二:创建自定义网络(不影响其他容器)

如果不想改全局配置,可以只为项目新建网络:

docker network create --subnet=172.31.0.0/16 mynet

运行容器时指定:

docker run --network=mynet ...

或在 docker-compose.yml 中指定:

networks:
  default:
    ipam:
      config:
        - subnet: 172.31.0.0/16

这样,容器的内部网段就不会与阿里云冲突。


🧩 方案三:使用宿主机网络(临时方案)

如果只是临时测试,也可以直接使用宿主机网络:

docker run --network=host ...

容器直接复用宿主机网络栈,不再受 Docker 虚拟网段影响。

不过这种方式会暴露端口,不太适合生产环境。


🧠 五、排查与解决总结

现象 根因 解决方式
ping 不通 Docker 与目标网段冲突 修改 Docker 网段
nc 超时 路由错误或安全组问题 检查路由或安全组
其他容器正常 当前容器网络错误 使用自定义网络
所有容器都不通 Docker 默认 bridge 冲突 /etc/docker/daemon.json

💬 六、结语

这次问题的关键在于:

Docker 默认的 172.18.0.0/16 网段,与阿里云 Redis 内网网段冲突,导致容器内流量无法正确路由。

改一下 Docker 的默认网段,就能立刻恢复正常。


🧾 总结一句话:

遇到 “No route to host” 错误时,别急着查防火墙,先看 Docker 的网段冲不冲突!

正文完
 0
评论(没有评论)
验证码