在 openEuler 上排查 Docker 同桥网络不通:从“全线超时”到定位容器没启动
目录
在 openEuler 上排查 Docker 同桥网络不通:从“全线超时”到定位容器没启动
一、现象与环境
二、排查思路总览
三、关键症状定位:同桥“全线超时”
四、openEuler 特有的“坑位”:桥与防火墙联动
1)先确认/放开内核和 firewalld
2)iptables 的 FORWARD 规则补齐
3)**反向路径过滤(rp_filter)**一网打尽
4)核心修复:关闭“桥层 → iptables/nft”联动
五、验证网络恢复(你的“核心命令”)
六、最后的真相:OpenWebUI 容器没启动
七、附:Postgres 侧看到的另一个坑(账号)
八、Checklist:openEuler 上 Docker 同桥互通排障清单
九、持久化建议
十、结语
在 openEuler 上排查 Docker 同桥网络不通:从“全线超时”到定位容器没启动
这是一篇记录式技术笔记,复盘一次在 openEuler 24.03 (LTS-SP2) 上排查
docker-compose
部署的 OpenWebUI/Milvus/MinIO/Postgres 集群“容器间网络不通、应用反复重启”的全过程。
关键收获:先把“网络层”排干净,再盯应用自身进程状态;在 openEuler 上,bridge ↔ iptables/nft 的联动是第一嫌疑。
一、现象与环境
-
现象:
-
openwebui
与 Milvus/MinIO/Postgres 互相报“连不上”;OpenWebUI 访问 8080 不通。 -
docker run --rm --network openwebui busybox ... nc
同桥互测,最初全部超时。
-
-
环境:
-
OS:openEuler 24.03 (LTS-SP2)
-
Docker:自建 bridge 网络
openwebui
(子网172.18.0.0/16
) -
关键容器:
openwebui
、openwebui-postgres
、openwebui-minio
等
-
二、排查思路总览
-
确认容器网络拓扑:容器都在同一
openwebui
网络,有分配172.18.0.x
。 -
同桥探活:用一次性
busybox
/nc
在 容器网络内 测各服务端口。 -
宿主网络策略:依次排除 firewalld / iptables /
rp_filter
/bridge-nf-*
/ nft-bridge / ebtables 干扰。 -
抓包判定路径:必要时
tcpdump
抓桥接口,看包是否进桥、是否返回。 -
应用自身:当网络确认畅通但端口还是“closed”,就检查服务是否真正启动、是否监听 0.0.0.0。
-
最终结论:本例中,网络层问题解决后,OpenWebUI 访问不了的直接原因其实是容器没启动(或启动失败后退出),不是网络。
三、关键症状定位:同桥“全线超时”
首先在 openwebui
网络里跑一次性容器做端口探测(务必在容器网络内,而非宿主):
docker run --rm --network openwebui busybox sh -c 'nslookup openwebui-postgres || truenslookup openwebui-minio || truenc -zvw3 openwebui-postgres 5432 && echo "PG OPEN" || echo "PG CLOSED";nc -zvw3 openwebui-minio 9000 && echo "MINIO OPEN" || echo "MINIO CLOSED"
'
最初看到的是 全部 CLOSED/timeout;ping
网关 172.18.0.1
却是 OK,说明 L3 路由在,桥内转发被拦的概率很高。
四、openEuler 特有的“坑位”:桥与防火墙联动
1)先确认/放开内核和 firewalld
# 载入桥过滤模块(存在即可)
modprobe br_netfilter 2>/dev/null || true# 放开内核三层转发
sysctl -w net.ipv4.ip_forward=1#(如果 firewalld 开着)把 docker 网桥放进 trusted
BRID=$(docker network inspect openwebui -f '{{.Id}}' | cut -c1-12)
BRIF="br-$BRID"
firewall-cmd --zone=trusted --add-interface="$BRIF" --permanent
firewall-cmd --reload
2)iptables 的 FORWARD 规则补齐
iptables -I FORWARD -o "$BRIF" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD -o "$BRIF" -j DOCKER 2>/dev/null || true
iptables -I FORWARD -i "$BRIF" ! -o "$BRIF" -j ACCEPT
iptables -I FORWARD -i "$BRIF" -o "$BRIF" -j ACCEPT
3)**反向路径过滤(rp_filter)**一网打尽
只改
all/default/bridge
不够,每个 veth 接口也要改*。
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > "$f"; done
4)核心修复:关闭“桥层 → iptables/nft”联动
在 openEuler 上这三项 置 0 很关键,很多“同桥互通超时”的根因都是它们。
modprobe br_netfilter 2>/dev/null || true
sysctl -w net.bridge.bridge-nf-call-iptables=0
sysctl -w net.bridge.bridge-nf-call-ip6tables=0
sysctl -w net.bridge.bridge-nf-call-arptables=0 2>/dev/null || true
执行完这三条之后,同桥网络立刻恢复:Postgres/MinIO 端口都能 OPEN
了。
五、验证网络恢复(你的“核心命令”)
下面这组命令就是最终把网络判定清楚的关键闭环:
modprobe br_netfilter 2>/dev/null || true
sysctl -w net.bridge.bridge-nf-call-iptables=0
sysctl -w net.bridge.bridge-nf-call-ip6tables=0
sysctl -w net.bridge.bridge-nf-call-arptables=0 2>/dev/null || truedocker run --rm --network openwebui busybox sh -c 'nc -zvw2 openwebui 8080 && echo OWUI_OPEN || echo OWUI_CLOSED;nc -zvw2 openwebui-postgres 5432 && echo PG_OPEN || echo PG_CLOSED;nc -zvw2 openwebui-minio 9000 && echo MINIO_OPEN || echo MINIO_CLOSED
'
# 输出(当时):
# OWUI_CLOSED
# openwebui-postgres (172.18.0.6:5432) open
# PG_OPEN
# openwebui-minio (172.18.0.3:9000) open
# MINIO_OPEN
这说明:同桥网络已经通了(PG/MinIO OPEN),唯独 OpenWebUI 8080 仍未开放。
六、最后的真相:OpenWebUI 容器没启动
到这一步,“网络问题”已被排除,继续看 OpenWebUI 的容器/进程状态:
-
docker ps -a
看状态是否Up
;若频繁Restarting
,看docker logs openwebui
报什么; -
容器内看监听地址是否为
0.0.0.0:8080
:docker exec -it openwebui sh -lc '(ss -lntp 2>/dev/null || netstat -lntp 2>/dev/null || true) | egrep "8080|LISTEN" || true '
本次真正的直接原因:OpenWebUI 容器本身没有启动成功(或启动就退出),导致 8080 “closed”。
把 OpenWebUI 的启动错误修复后(或绑到 0.0.0.0
正常监听),访问立即恢复。
七、附:Postgres 侧看到的另一个坑(账号)
修好网络后,Postgres 日志还有:
FATAL: role "gzj_kb" does not exist
这与网络无关,是应用使用了不存在的数据库用户。修法二选一:
-
A:把应用的
DATABASE_URL
改成库里已有的账号; -
B:在库里创建它想要的账号/库并授权:
docker exec -it openwebui-postgres psql -U postgres -d postgres -c "CREATE USER gzj_kb WITH PASSWORD '***';" docker exec -it openwebui-postgres psql -U postgres -d postgres -c "CREATE DATABASE openwebui OWNER gzj_kb;"
八、Checklist:openEuler 上 Docker 同桥互通排障清单
-
在容器网络内探活(busybox + nc),不要用宿主口:
docker run --rm --network <net> busybox sh -c 'nc -zvw3 <svc> <port>'
-
确认所有容器都在同一网络:
docker network inspect <net> --format '{{json .Containers}}' | jq
-
放开路由/防火墙:
-
sysctl -w net.ipv4.ip_forward=1
-
firewalld:把
br-<ID>
加到trusted
-
iptables FORWARD:四条放行规则(见上文)
-
-
rp_filter=0(全接口,包含 veth*):
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > "$f"; done
-
openEuler 关键:关闭 bridge → iptables/nft 过滤:
sysctl -w net.bridge.bridge-nf-call-iptables=0 sysctl -w net.bridge.bridge-nf-call-ip6tables=0 sysctl -w net.bridge.bridge-nf-call-arptables=0
-
仍不通时:检查 nftables bridge family、ebtables,必要时抓包
tcpdump -i br-<ID> ...
。 -
应用层:容器是否
Up
、是否监听0.0.0.0:<port>
,日志是否报错。 -
数据库层:账号/库是否存在、是否能
psql
成功。
九、持久化建议
# /etc/sysctl.d/98-bridge-off.conf
net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-arptables=0
# 以及(如需)
net.ipv4.ip_forward=1
sysctl --system
# firewalld 已 --permanent;若使用 nftables,自行保存规则:
nft list ruleset >/etc/sysconfig/nftables.conf
systemctl enable --now nftables 2>/dev/null || true
十、结语
这次问题表面看是“全链路网络不通”,实质是两层问题叠加:
-
系统层:openEuler 上的桥/防火墙联动(
bridge-nf-call-*
)导致同桥互通被拦。 -
应用层:OpenWebUI 自身没启动成功,导致 8080 端口始终“closed”。