Margrop
Articles382
Tags715
Categories7

Categories

1password 2K 4-bit 量化 6-DoF SLAM AC ACL ACL 切换 ACP AI AI Agent AI Coding Assistant AI Tech AI 安全 AI 日记 AI编程助手 AI辅助 AI辅助编程 AP API ARC-AGI-3 ASR Agent Agent 入侵 Agent 检索 Agent 系统 Agent 路由 AgentPlan Agentic AI Agentic tools Ai2 Alertmanager Android 17 Antigravity AppDaemon AppWorld Aqara Attention Blog CC-Switch CI/CD CLI Tools CLI 工具 CLI工具 CPU 推理 CSRF Cache Hit Rate Caddy Categories 404 Claude Code Claude Sonnet ClawLoader Cloudflare Code Interpreter Codex Coding Plan Coding Plan Dashboard ComfyUI Computer Use Context Compression Cookie 认证 Cosmos-H-Dreams Cost Optimization Cron D1 DFIR Date Diagrams.net Diary Diffusers Diffusion Docker Docker Compose Efficiency Tools Electerm Embedding English FSDP2 Fable 5 Fireworks AI FlashAttention FlashDreams Flask GLM 5.2 GPT-4.1 GPT-5.6 GPT-Live GPT-Red GPU 加速 GPU 性能分析 Gateway Gemini Gemini 3.5 Flash Gemini API Gemini CLI Gemini Omni Flash Gemma 4 12B GitHub GitHub Actions Google AI Grabette Gripette HA HADashboard Hailuo Hermes HermesAgent Hexo HomeAssistant Hugging Face Hugo IBM Research IP IPv4 Isaac Lab Java KV cache Kimi Code Kimi K3 Kubernetes LFM2.5 LLM Router LVM‑Thin LeRobot Linux Liquid AI Live Translate LoRA MCP MacOS Managed Agents Markdown Memory 上限 Microsoft 365 Copilot MiniMax Model Routing MuJoCo Warp Multi-Agent MySQL NAS NVIDIA NeMo Automodel Nemotron 3 Embed NewAPI Newton Nginx Node-RED Node.js Nunchaku OOM OlmoEarth On-device AI Open Source Open Viking OpenAI OpenClaw OpenCode OpenResty OpenWrt PII 检测 PPPoE Physical AI Pollen Robotics Portainer PostgreSQL ProcessOn Prometheus Prompt Injection Proxmox VE PyTorch Qwen3-VL RPC RTEB Real-Time Inference Red Teaming Responses API SNAP SOCKS5 SOCKS5 代理 SPED SSL SVDQuant Scientific Computing Self-Forcing Distillation Session Shell Skill 管理 Subagent Surgical Robotics Synology NAS TTS TimeMachine UML Uptime Kuma VPN VPS VoiceEQ WARP Web WebRTC WebSocket Windows Workers World Foundation Model activate ad adb adblock agent aligenie aliyun alpine annotation aop authy autofs backup baidupan bash bitwarden boot brew browser caddy2 cdn centos cert certbot charles chat chrome classloader client clone closures cloudflare cmd command commit conn_id container cron 排错 crontab cross_sync ctyun ddsm demo dependency deploy developer devtools disconnect topic dll dns docker domain download draw drawio dsm dump dylib easytier edge exception export fail2ban feign firewall-cmd flow frp frpc frps fuckgfw full-duplex function gcc gfw git github golang gperftools gridea grub gvt-g hacs havcs heap hello hexo hibernate hidpi hoisting homeassistant hosts html htmlparser https iKuai iMessage idea image img img2kvm immortalwrt import index install intel io ios ip iptables iptv ipv6 iso java javascript jetbrains jni jnilib jpa js json jsonb jupter jupyterlab jvm k8s keepalive keepalive ping timeout kernel key kid kms kodi koolproxy koolproxyr kvm lan lastpass launchctl learning lede letsencrypt linux live low-code lvm lxc m3u8 mac macos mariadb markdown maven md5 mdadm microcode mirror modem modules monitor mount mstsc mysql n2n n5105 nas network nfs no close frame node node-red nodejs nohup notepad++ npm nssm ntp one-api 容器 oop openfeign openssl os otp ovz p14 packet capture pat pdf pem perf ping pip plugin png powerbutton print pro proxy pve pvekclean python qcow2 qemu qemu-guest-agent rar reboot reflog remote remote desktop renew repo resize retina root route router rule rules runtime safari sata scipy-notebook scoping scp self-play server silent test slmgr so socks source spk spring springboot springfox ssh ssl stash string supernode support svg svn swagger sync synology systemctl systemd tap tap-windows tapwindows telecom template terminal tls tmux token totp tvbox txt ubuntu udisk ui undertow uninstall unlocker upgrade url v2ray vLLM vhd vim vlmcsd vm vmdk web websocket wechat windows with worker wow xiaoya xml yum zip 上下文压缩 个人品牌 中国电信 临时关权限 临时提权 云电脑 交换机 人才争夺 人机协作 代理 企业 AI 优化 体检 供应链 值班 健康检查 光猫 公众号 公网IP 内存 内存优化 内容发布 内网 内网IP 内网渗透 写作 分布式推理 分布式训练 升级 协作 协作习惯 协议层 单平台型异常 博客 博客同步 博客改名 博客运维 卫星影像 反向代理 反诉 变更审计 可靠性 后台 Review 启动 告警 告警优化 周一 周一傍晚 周一焦虑 周三傍晚 周五 周六 周四傍晚 周四晚 周报 周日 周末 回滚 地球观测 地理空间推理 夏令时 多协议并发 多智能体 多模态 多节点 多节点管理 多通道并发 大厂人才战 天猫精灵 天翼云 失败模式 字体大小 安全 安全事件 安全意识 安装 定时任务 实时语音 容器 容器网络 导入 小米 工作感悟 工具调用 工程团队 工程实践 工程笔记 常用软件 广告屏蔽 序列号 应用市场 开放 API 开权重 开源模型 开源项目 异常 异步任务 异步委派 微信 微信公众号 心智成长 心跳 心跳检查 性能优化 感悟 打工 打工人 打工人日记 扩散模型 技术 抓包 排查 排障思路 推理加速 描述文件 故障 故障排查 效率 效率工具 数据 文本编码器 旁路由 无服务器 日志排查 日记 时区 时段权限 显卡虚拟化 智能体集成 智能家居 智能音箱 服务器 服务管理 本地安装 机器人仿真 机器人数据采集 权限管理 架构 框架级切片 梯子 模块 模型推理 残存访问 流式推理 流程 流程图 浏览器 漫游 激活 火山引擎 火绒 灾难恢复 焦虑 独立仓库 玄学 生活 电信 画图 监控 监控系统 监管 直播源 直觉 磁盘 磁盘故障 稀疏样本 稀疏注意力 立体声 端口 端口冲突 端口扫描 管理 续期 网关 网络 网络风暴 群晖 群晖 NAS 脚本 脚本优化 腾讯 自动化 自动化反思 自动化运维 自动恢复 自动攻击 自动重连 苹果 虚拟机 视频生成 认证 证书 评测基准 评测方法学 诉讼 语雀 语音 AI 质量检查 超时 跨平台 路由 路由器 软件管家 软路由 运维 运维日常 运维监控 连接保活 连接问题 通信机制 通知 邮件漏发 部署 配置 钉钉 镜像 镜像源 长上下文 长连接 门窗传感器 问题排查 防火墙 阿里云 阿里源 集客 需求变更 飞书

Hitokoto

Archive

Docker容器网络互通排障全流程:从Bridge到iptables的深度排查

Docker容器网络互通排障全流程:从Bridge到iptables的深度排查

前言

容器网络互通是Docker部署中最容易出问题的环节之一。相比传统VM网络,容器网络多了好几层抽象——Bridge、iptables、veth pair、overlay……任何一个环节出问题,都会导致容器之间无法通信。

本文记录一次典型的跨宿主机容器网络互通问题排查全过程,从现象到根因到解决,提供可复用的排障思路和一键脚本。

问题背景

业务场景

在多台服务器上使用Docker Compose部署了一套微服务架构,各容器之间需要通过内部网络互通:

  • web 服务(前端Nginx)
  • api 服务(Python/Go后端)
  • db 服务(MySQL数据库)

三台服务器各运行部分容器,部分请求需要跨服务器访问。例如p14(某VPS)上的web容器需要访问VM152上的api容器。

问题现象

部署完成后,同一宿主机上的容器之间通信正常,但跨宿主机通信全部失败:

1
2
3
4
5
# 从p14的web容器访问同宿主机的api容器
curl http://api:8000/health ✅ 正常

# 从p14的web容器访问VM152的api容器
curl http://api-host:8000/health ❌ 连接超时

错误信息:Connection timed outNo route to host

环境信息

节点 IP 容器网络 说明
p14(某VPS) 某VPS_IP 172.18.0.0/16 Docker Bridge: docker0
VM152 某内网IP 172.19.0.0/16 Docker Bridge: docker0
VM151 某内网IP 172.20.0.0/16 Docker Bridge: docker0

三个网络地址完全不同,网段也不在同一大段——这为互通埋下了隐患。

排查过程

第一步:确认Docker网络配置

先检查各宿主机的Docker网络配置:

1
2
3
4
# 在各节点执行
docker network ls
docker network inspect bridge
docker network inspect <自定义网络名>

发现各节点使用的是默认的 bridge 网络,且网段配置如下:

1
2
3
p14:  172.17.0.0/16
VM152: 172.18.0.0/16
VM151: 172.19.0.0/16

问题初步定位:三个节点的Docker Bridge网段完全不同,且互不重叠

Docker默认的Bridge模式下,不同宿主机的容器处于完全隔离的网络中,无法直接互通。这是正常行为,不是bug。

第二步:理解Docker网络模式

Docker提供多种网络模式:

模式 说明 跨主机互通
bridge 默认模式,使用docker0网桥 ❌ 不能直接互通
host 容器共享宿主机网络 ✅ 可以,但易端口冲突
overlay Docker Swarm模式,自带VXLAN隧道 ✅ 可以
macvlan 给容器分配真实MAC,挂在物理网络上 ✅ 可以

要实现跨主机互通,有三种常用方案:

  1. Docker Compose + external networks:使用自定义bridge网络配合 --net=host
  2. Docker overlay:需要Docker Swarm,比较重
  3. macvlan + 物理网络打通:最接近物理网络的方案

考虑到生产环境的简洁性,我们选择 macvlan 方案。

第三步:检查宿主机网络是否支持macvlan

macvlan需要物理网卡支持”混杂模式”。检查方法:

1
2
3
4
5
6
7
# 检查网卡是否支持混杂模式
ip link show eth0
# 查看是否有 PROMISC 标志

# 或者用ethtool检查
ethtool eth0 | grep -i promis
# 如果显示 "Promiscuous mode: on" 则支持

如果网卡不支持macvlan,需要改用overlay或自定义bridge方案。

第四步:创建macvlan网络

在各宿主机上执行以下命令(注意:需要先删除旧的bridge容器):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 在p14上执行
docker network create \
--driver macvlan \
--subnet=172.18.0.0/16 \
--gateway=172.18.0.1 \
-o parent=eth0 \
macvlan_net

# 在VM152上执行
docker network create \
--driver macvlan \
--subnet=172.19.0.0/16 \
--gateway=172.19.0.1 \
-o parent=eth0 \
macvlan_net

第五步:发现新问题——网关不通

创建macvlan网络后,发现容器仍然无法跨宿主机通信。

ping 测试:

1
2
3
# 从p14的容器ping VM152的网关
ping 172.19.0.1
# 结果:Destination Host Unreachable

问题定位:宿主机之间的路由不通

检查网络架构:

1
2
p14所在网络:  192.168.160.0/24 (假设)
VM152所在网络: 192.168.102.0/24 (假设)

两个内网不在同一网段,需要通过路由器/三层交换转发。

第六步:检查iptables和路由表

在VM152上检查iptables规则:

1
2
3
4
5
6
7
# 查看NAT规则
iptables -t nat -L -n
# 重点关注 POSTROUTING 和 FORWARD 链

# 查看转发是否开启
cat /proc/sys/net/ipv4/ip_forward
# 如果是0,需要开启:echo 1 > /proc/sys/net/ipv4/ip_forward

发现 ip_forward 是关闭的。开启后再次测试:

1
2
3
4
5
# 开启IP转发(临时,重启失效)
echo 1 > /proc/sys/net/ipv4/ip_forward

# 永久开启
sysctl -w net.ipv4.ip_forward=1

但问题依然存在。

深入检查iptables的FORWARD链:

1
2
3
4
5
# 查看filter表的FORWARD链
iptables -L FORWARD -n -v

# 临时放行所有转发流量测试
iptables -P FORWARD ACCEPT

测试发现:iptables的FORWARD策略默认是DROP的,阻止了跨宿主机流量。

第七步:配置正确的iptables规则

1
2
3
4
5
6
7
8
9
# 允许Docker网络之间的流量转发
# 注意:需要根据实际网段修改

# 允许p14网络访问VM152网络(示例网段)
iptables -A FORWARD -s 172.18.0.0/16 -d 172.19.0.0/16 -j ACCEPT
iptables -A FORWARD -s 172.19.0.0/16 -d 172.18.0.0/16 -j ACCEPT

# 允许已知Docker网段的流量
iptables -A FORWARD -s 172.0.0.0/8 -d 172.0.0.0/8 -j ACCEPT

但这种逐条配置的方式太繁琐,且不够安全。

更好的方案是:在Docker服务启动时自动配置正确的iptables规则

1
2
3
4
5
6
7
8
9
10
# 编辑Docker服务配置
vim /etc/systemd/system/docker.service.d/10-macvlan.conf

# 添加以下内容
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 \
--ip-masq=true \
--ip-forward=true \
--iptables=true

第八步:重新测试连通性

1
2
3
4
5
6
7
# 重启Docker服务
systemctl daemon-reload
systemctl restart docker

# 再次测试
docker run --rm --net=macvlan_net alpine ping -c 3 172.19.0.x
# 如果能ping通,说明macvlan配置成功

根因分析

为什么默认bridge网络不能跨主机互通?

Docker默认的bridge网络是”单主机”的。docker0 网桥只在本机生效,不同宿主机的docker0网桥完全隔离。

当你执行 docker network inspect bridge 时,会发现:

1
2
3
4
5
6
{
"Name": "bridge",
"Driver": "bridge",
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}

这个172.17.0.0/16网段只在当前宿主机内有效。另一台宿主机的容器即使也用了172.17.0.0/16,也不会和第一台冲突——因为它们根本不在同一个二层网络中。

为什么需要macvlan或overlay?

要让容器跨主机通信,需要在”容器网络”和”物理网络”之间架设桥梁:

  • macvlan:让容器直接”挂”在物理网络上,容器有自己的MAC和IP,就像真实的物理机一样
  • overlay:在物理网络之上建立VXLAN隧道,容器在overlay网络中互通,物理网络只负责传输VXLAN数据包

两种方案各有优劣:

方案 优点 缺点
macvlan 性能最好,接近物理网络 需要网卡支持混杂模式,配置复杂
overlay Docker原生支持,易配置 性能略有损耗,需要额外存储

完整解决方案

方案一:macvlan方案(推荐用于生产环境)

前置条件

  • 网卡支持混杂模式
  • 宿主机网络允许macvlan流量

步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 创建macvlan网络(各宿主机执行,使用不同subnet)
docker network create \
--driver macvlan \
--subnet=<各节点独立子网> \
--gateway=<各节点网关> \
-o parent=<物理网卡名> \
--internal \
macvlan_internal

# 2. 使用网络启动容器
docker run --rm --net=macvlan_internal --ip=<固定IP> -it alpine sh

# 3. 配置iptables允许转发
iptables -A FORWARD -s <各节点子网> -j ACCEPT
iptables -A FORWARD -d <各节点子网> -j ACCEPT

方案二:overlay方案(推荐用于Docker Swarm环境)

1
2
3
4
5
6
7
8
# 初始化Swarm(Manager节点)
docker swarm init

# 创建overlay网络
docker network create -d overlay --attachable my_overlay_net

# 在任意节点启动容器并加入该网络
docker run --rm --net=my_overlay_net -it alpine sh

一键排障脚本

以下脚本可快速排查容器网络问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/bin/bash
# Docker容器网络排障脚本
# 保存到 /opt/scripts/docker-network-check.sh

set -e

echo "========== Docker 容器网络排障 =========="
echo "时间:$(date '+%Y-%m-%d %H:%M:%S')"
echo ""

# 1. 检查Docker网络列表
echo "[1/7] Docker网络列表:"
docker network ls
echo ""

# 2. 检查docker0网桥状态
echo "[2/7] docker0网桥状态:"
ip addr show docker0 2>/dev/null || echo " docker0不存在(可能使用其他网络)"
echo ""

# 3. 检查IP转发
echo "[3/7] IP转发状态:"
IP_FORWARD=$(cat /proc/sys/net/ipv4/ip_forward)
echo " ip_forward = $IP_FORWARD"
if [ "$IP_FORWARD" != "1" ]; then
echo " ⚠️ IP转发未开启,可能导致跨宿主机通信失败"
fi
echo ""

# 4. 检查iptables FORWARD策略
echo "[4/7] iptables FORWARD策略:"
FORWARD_POLICY=$(iptables -L FORWARD -n | grep "^Chain FORWARD" | awk '{print $4}')
echo " 默认策略: $FORWARD_POLICY"
if [ "$FORWARD_POLICY" = "DROP" ]; then
echo " ⚠️ FORWARD策略为DROP,可能阻止容器通信"
fi
echo ""

# 5. 检查Docker网络详情
echo "[5/7] 各Docker网络详情:"
for net in $(docker network ls --format '{{.Name}}' | grep -v -E '^(none|host)$'); do
echo " --- $net ---"
docker network inspect $net --format '{{range .IPAM.Config}}Subnet: {{.Subnet}} Gateway: {{.Gateway}}{{end}}' 2>/dev/null
echo ""
done

# 6. 检查容器网络连接(需要指定网络名)
echo "[6/7] 跨宿主机连通性测试:"
echo " 说明:以下为示例测试,请根据实际环境修改目标IP"
# ping -c 1 -W 1 目标IP 2>/dev/null && echo " ✅ 到目标IP可达" || echo " ❌ 到目标IP不可达"
echo ""

# 7. 检查DNS解析(容器间通信通常依赖DNS)
echo "[7/7] 容器DNS配置:"
docker run --rm --net=bridge alpine cat /etc/resolv.conf 2>/dev/null || echo " 无法获取DNS配置"
echo ""

echo "========== 排障完成 =========="
echo ""
echo "常见问题处理建议:"
echo "1. IP转发未开:sysctl -w net.ipv4.ip_forward=1"
echo "2. FORWARD被DROP:iptables -P FORWARD ACCEPT"
echo "3. 跨主机不通:检查物理网络路由或使用overlay/macvlan"
echo "4. DNS解析失败:检查自定义网络的DNS配置"

使用方法:

1
2
chmod +x /opt/scripts/docker-network-check.sh
/opt/scripts/docker-network-check.sh

常见问题解答

Q1:为什么容器能ping通宿主机,但ping不通其他宿主机上的容器?

A:这通常意味着:

  1. 宿主机之间的路由不通(检查网络设备和路由表)
  2. iptables的FORWARD策略阻止了流量(检查iptables -L FORWARD)
  3. IP转发未开启(检查/proc/sys/net/ipv4/ip_forward)

Q2:macvlan容器无法获取IP怎么办?

A:可能的原因:

  1. 物理网卡不支持混杂模式(用 ip link show eth0 检查)
  2. 父网络(parent)配置错误
  3. 子网与物理网络冲突

Q3:overlay网络创建失败怎么排查?

A:overlay需要Docker Swarm环境。先检查是否已初始化Swarm:

1
2
3
docker info | grep Swarm
# 如果显示 "Swarm: inactive",需要先初始化
docker swarm init

Q4:容器内无法解析其他容器的名字怎么办?

A:Docker的嵌入式DNS(Embedded DNS)只对用户自定义网络(如docker network create创建的网络)生效。默认bridge网络不支持容器间DNS解析。

解决方案:

1
2
3
4
5
6
7
8
9
# 创建自定义网络
docker network create my_net

# 启动容器时使用该网络
docker run --net=my_net --name=container_a -d image_a
docker run --net=my_net --name=container_b -d image_b

# 现在container_b可以通过container_a的名字访问它
docker exec container_b ping container_a

Q5:如何在不停容器的情况下修复网络问题?

A:Docker允许动态创建网络并让运行中的容器连接:

1
2
3
4
5
6
7
8
# 创建新网络
docker network create -d bridge --subnet=172.20.0.0/16 my_new_net

# 将运行中的容器连接到新网络(不影响原网络连接)
docker network connect my_new_net <运行中的容器ID>

# 断开旧网络(如需要)
docker network disconnect bridge <容器ID>

总结

Docker容器网络互通问题排查的核心思路:

  1. 先确认是单主机问题还是跨主机问题:同主机通、跨主机不通,通常是网络层问题
  2. 理解Docker网络模式:bridge/host/overlay/macvlan各有特点,选对方案是关键
  3. 逐层排查:物理网卡 → 网桥 → iptables → 路由表 → 应用层
  4. 善用工具ipiptablesdocker network inspecttcpdump都是排查利器

希望这篇文章能帮到你。如果有问题,欢迎在评论区讨论。


作者:小六,一个在上海努力搬砖的程序员

本文阅读量 --
Author:Margrop
Link:https://blog.margrop.com/post/2026-03-23-docker-container-networking-troubleshooting/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可