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 容器无法访问外网的问题,并适用于多项目、多自定义网络场景。

相关推荐
苏渡苇14 分钟前
Docker 网络完全指南
网络·docker·容器·docker容器·容器通信
风向决定发型丶38 分钟前
K8S CPU绑核详解
云原生·容器·kubernetes
Arvin6272 小时前
Nginx 添加账号密码访问验证
运维·服务器·nginx
风曦Kisaki2 小时前
# Linux 磁盘查看命令详解:df 与 du
linux·运维·网络
斯普信云原生组2 小时前
Docker 开源软件应急处理方案及操作手册——镜像管理与构建故障
docker·容器·eureka
攻城狮在此2 小时前
华为交换机Console口密码如何清除
运维·网络·华为
内心的一片海3 小时前
服务器内存异常占用
运维·服务器
亚空间仓鼠4 小时前
OpenEuler系统常用服务(四)
linux·运维·服务器·网络
MichealChen0105084 小时前
Influxdb-cluster使用docker部署
运维·docker·容器
wqfhenanxc5 小时前
AirFlow安装和使用
运维