Docker 容器无法访问外网的问题排查与解决指南

Docker 容器无法访问外网的问题排查与解决指南

在使用 Docker Compose 部署多容器项目时,有时会遇到容器无法访问外网的情况。本文将以一个虚拟示例系统为基础,介绍问题出现的原因、排查思路和最终解决方法。


一、问题描述

假设我们有一个项目 demo-project,包含多个服务容器,例如:

  • demo-redis
  • demo-mysql
  • demo-app
  • demo-gateway

在容器中执行:

bash 复制代码
docker-compose exec demo-app sh
ping 8.8.8.8

发现容器无法 ping 通外网 IP,说明容器不能访问外网。


二、排查思路

排查 Docker 容器网络问题,一般按照以下步骤:

1️⃣ 检查容器 DNS 与 IP 访问

  • 先尝试访问 IP:
bash 复制代码
ping 8.8.8.8
  • 结果

    • 如果可以 ping 通 → DNS 配置问题
    • 如果不能 ping → NAT 或网桥配置问题

本次案例中,ping 8.8.8.8 失败,说明问题在 NAT 或宿主机路由层。


2️⃣ 查看 Docker 自定义网络

bash 复制代码
docker network ls
docker network inspect demo_project_network
  • 查找自定义网络子网,例如:172.30.0.0/16
  • Docker 会在宿主机上生成对应的 Linux 网桥接口,例如 br-abcdef123456
  • 注意网桥 IP 与子网网关配置,例如 172.30.0.1/16

3️⃣ 检查宿主机 IP 转发

bash 复制代码
sysctl net.ipv4.ip_forward
  • 如果值为 0,容器无法出网,需要开启:
bash 复制代码
sudo sysctl -w net.ipv4.ip_forward=1

4️⃣ 检查 iptables NAT 规则

bash 复制代码
sudo iptables -t nat -L -n
  • 如果 POSTROUTING 链为空,说明没有 SNAT/MASQUERADE 规则
  • 容器子网流量出宿主机时没有被 NAT,就无法访问外网

三、解决办法

1️⃣ 添加 MASQUERADE 规则

在宿主机上执行:

bash 复制代码
sudo iptables -t nat -A POSTROUTING -s 172.30.0.0/16 ! -o br-abcdef123456 -j MASQUERADE
  • -s 172.30.0.0/16:容器子网
  • ! -o br-abcdef123456:排除容器内部通信
  • -j MASQUERADE:动态 SNAT,把源 IP 改为宿主机公网 IP

规则立即生效,容器可以立即访问外网。

2️⃣ 确认生效

在容器中测试:

bash 复制代码
docker-compose exec demo-app sh
ping 8.8.8.8
curl http://example.com

如果可以 ping 通 IP 和访问网站,说明配置成功。


3️⃣ 多项目情况

如果宿主机上运行多个 Docker Compose 项目:

  • 每个项目自定义网络的子网不同,例如:

    • 项目 A:172.30.0.0/16 → br-abcdef123456
    • 项目 B:172.31.0.0/16 → br-123456abcdef
  • 每个网络都需要添加一条 MASQUERADE 规则:

bash 复制代码
sudo iptables -t nat -A POSTROUTING -s 172.30.0.0/16 ! -o br-abcdef123456 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -s 172.31.0.0/16 ! -o br-123456abcdef -j MASQUERADE

或者编写脚本自动扫描所有自定义网络添加规则。


四、知识点扩展

1️⃣ MASQUERADE 与 NAT

  • NAT(Network Address Translation)是网络地址转换

  • MASQUERADE 是一种动态 SNAT,常用于容器或路由器出网

  • 容器出网流程:

    容器 IP → Docker 网桥 → iptables MASQUERADE → 宿主公网 IP → 外网

2️⃣ br-* 网桥接口

  • Docker 自定义网络会在宿主机创建对应网桥,命名规则:br-<网络ID前缀>
  • 容器通过该网桥通信和出网
  • NAT 规则里排除这个接口,避免内部通信被误 NAT

五、总结

  1. 容器无法出网,先确认是 DNS 问题 还是 NAT/路由问题
  2. 查看 Docker 自定义网络和对应网桥接口
  3. 确保宿主机开启 IP 转发
  4. 添加 POSTROUTING MASQUERADE 规则让容器出公网
  5. 多项目需要针对不同子网分别添加规则

通过上述步骤,可以系统解决 Docker 容器无法访问外网的问题,并适用于多项目、多自定义网络场景。

相关推荐
聆风吟º18 小时前
CANN开源项目深度实践:基于amct-toolkit实现自动化模型量化与精度保障策略
运维·开源·自动化·cann
较劲男子汉1 天前
CANN Runtime零拷贝传输技术源码实战 彻底打通Host与Device的数据传输壁垒
运维·服务器·数据库·cann
风流倜傥唐伯虎1 天前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
Doro再努力1 天前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
senijusene1 天前
Linux软件编程:IO编程,标准IO(1)
linux·运维·服务器
忧郁的橙子.1 天前
02-本地部署Ollama、Python
linux·运维·服务器
醇氧1 天前
【linux】查看发行版信息
linux·运维·服务器
lpruoyu1 天前
【Docker进阶-03】存储原理
docker·容器
No8g攻城狮1 天前
【Linux】Windows11 安装 WSL2 并运行 Ubuntu 22.04 详细操作步骤
linux·运维·ubuntu
酷酷的崽7981 天前
CANN 生态可维护性与可观测性:构建生产级边缘 AI 系统的运维体系
运维·人工智能