专业编程基础技术教程

网站首页 > 基础教程 正文

解决Docker容器内网络故障:从多网卡冲突到网络配置优化

ccvgpt 2025-01-20 11:11:06 基础教程 7 ℃

最近在使用Docker时,可能会遇到容器无法访问外网的问题。本篇文章记录了一个从问题发现到最终解决的完整过程,涵盖了问题分析、尝试解决方案以及最终的成功经验,希望能为遇到类似问题的读者提供参考。


背景

在某次部署Docker服务时,我发现运行的容器无法访问外网。例如,执行以下命令时:

解决Docker容器内网络故障:从多网卡冲突到网络配置优化

sudo docker run --rm alpine ping -c 4 security.ubuntu.com

容器内返回的结果是:

ping: bad address 'security.ubuntu.com'

通过多次排查后发现,问题不仅仅是DNS配置的问题,而是与宿主机的多网卡和网络路由冲突相关。本篇记录了问题的完整解决过程。


问题分析

初步排查

  1. 检查容器内的DNS配置: 使用以下命令进入容器并查看DNS配置:
sudo docker run --rm -it alpine sh
cat /etc/resolv.conf

结果显示DNS配置正确:

nameserver 8.8.8.8
nameserver 8.8.4.4
  1. 测试直接访问IP地址: 在容器中尝试直接访问 security.ubuntu.com 的IP地址:
ping -c 4 91.189.91.81

结果同样无法访问。这表明问题不仅仅是DNS解析,而是网络连接本身的问题。

  1. 检查宿主机的Docker网桥 (docker0) 状态
ip link show docker0

结果显示 docker0 的状态为 DOWN,说明Docker的默认网桥未正常工作。

  1. 查看宿主机路由表
ip route

路由表显示存在多个默认网关:

default via 192.168.2.1 dev ens32 proto static
default via 122.147.187.1 dev ens33 proto static

这表明宿主机存在两个网卡(ens32 和 ens33),并且都配置了默认路由,可能导致路由冲突。


解决问题的尝试过程

1. 重建Docker网桥 (docker0)

首先尝试手动删除并重建 docker0 网桥:

sudo ip link set docker0 down
sudo brctl delbr docker0
sudo brctl addbr docker0
sudo ip addr add 192.168.200.1/24 dev docker0
sudo ip link set docker0 up

重新启动Docker服务后,检查 docker0 的状态为 UP:

ip addr show docker0

尽管 docker0 已正常工作,但容器内的网络问题依然存在。


2. 强制刷新和重建NAT配置

尝试清空并重建宿主机的NAT配置:

sudo iptables -t nat -F
sudo iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -d 172.17.0.0/16 -j MASQUERADE
sudo iptables -P FORWARD ACCEPT

重新启动Docker服务并测试容器网络,问题仍未解决。


3. 修改Docker默认网桥IP

怀疑 docker0 使用的IP段可能与现有网络冲突,于是修改Docker默认网桥的IP段。

编辑 /etc/docker/daemon.json:

{
  "dns": ["8.8.8.8", "8.8.4.4"],
  "bip": "192.168.200.1/24"
}

重新启动Docker服务:

sudo systemctl restart docker

问题依然未解决。


4. 禁用多余网卡(ens32)

发现宿主机中存在两个网卡,并且都设置了默认路由。怀疑这是导致网络流量被错误路由的原因。

临时禁用 ens32:

sudo ip link set ens32 down

禁用后,容器内的网络测试成功:

sudo docker run --rm alpine ping -c 4 security.ubuntu.com

最终解决方案

经过排查,确认问题根源是宿主机的多网卡和多默认路由配置冲突。以下是最终的解决方案:

修改Netplan配置

编辑宿主机的 netplan 配置文件 /etc/netplan/*.yaml,确保只有一个默认网关(保留 ens33):

network:
    version: 2
    ethernets:
        ens32:
            addresses:
            - 192.168.2.95/24
            nameservers:
                addresses: []
                search: []
        ens33:
            addresses:
            - 122.147.187.95/24
            nameservers:
                addresses:
                - 168.95.1.1
                - 8.8.8.8
                search: []
            routes:
            -   to: default
                via: 122.147.187.1

应用Netplan配置

sudo netplan apply

验证路由表,确保只有一个默认路由:

ip route

结果应类似于:

default via 122.147.187.1 dev ens33 proto static
192.168.2.0/24 dev ens32 proto kernel scope link src 192.168.2.95

测试和验证

  1. 测试容器的DNS解析
sudo docker run --rm alpine nslookup security.ubuntu.com
  1. 测试容器的外网连接
sudo docker run --rm alpine ping -c 4 security.ubuntu.com
  1. 结果
  • 容器内的网络恢复正常。
  • 宿主机的多网卡冲突问题解决。

总结

本次问题的根源是宿主机的多网卡和多默认网关配置冲突,导致Docker容器的网络流量无法正确路由到外网。通过以下步骤最终解决了问题:

  1. 删除多余的默认网关。
  2. 修改 netplan 配置,确保宿主机只有一个默认路由。
  3. 调整Docker的默认网桥配置。

通过这次排查,可以更加深入理解了Docker的网络机制以及宿主机网络配置的重要性,希望这篇备忘录能帮助遇到类似问题的读者快速定位和解决问题。

Tags:

最近发表
标签列表