Docker 网桥名不固定导致容器间通信被 firewalld 阻断的排查与修复
问题背景
在阿里云服务器上部署了 Halo 博客(Docker Compose 编排,包含 Halo + PostgreSQL 两个容器),同时启用了 firewalld 作为主机防火墙。某天重启 firewalld 后,Halo 突然无法连接数据库,日志报错:
NoRouteToHostException: postgres/10.255.3.3:5432
但 PostgreSQL 容器状态正常(healthy),两个容器也在同一个 Docker 网络中。
根因分析
排查过程
- 确认容器状态:
docker ps显示两个容器均正常运行,PG 健康检查通过 - 确认网络归属:
docker inspect确认两容器同属halo-pg_default网络 - 检查防火墙:发现 firewalld 启动后,Docker 网桥接口未被分配到任何 zone,默认走 public zone,FORWARD 链拒绝了容器间的流量
根本原因
Docker Compose 自动创建的网络,其网桥名称是动态生成的(如 br-2b8a173f9081)。当执行 docker-compose down 再 up 时,旧网络被删除、新网络被创建,网桥名称会发生变化。
如果之前手动将旧网桥名加入了 firewalld trusted zone,新网桥名不在 trusted zone 中,容器间 FORWARD 流量就会被 firewalld 默认拒绝。
解决方案:固化网桥名
1. 修改 docker-compose.yml
在文件末尾追加 networks 配置,指定固定网桥名:
networks:
default:
driver_opts:
com.docker.network.bridge.name: br-halo-pg
2. 更新 firewalld trusted zone
# 添加固定网桥名到 trusted zone(持久化)
sudo firewall-cmd --permanent --zone=trusted --add-interface=br-halo-pg
# 移除旧的动态网桥名(可选)
sudo firewall-cmd --permanent --zone=trusted --remove-interface=br-2b8a173f9081
# 重载使配置生效
sudo firewall-cmd --reload
3. 重建 Docker 网络
cd /path/to/docker-compose-dir
sudo docker compose down
sudo docker compose up -d
4. 验证
# 确认新网桥已创建
ip link show br-halo-pg
# 确认 trusted zone 包含新网桥
sudo firewall-cmd --zone=trusted --list-interfaces
# 输出: br-halo-pg
# 确认服务正常
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8090
# 输出: 200
各场景下的行为对比
| 场景 | 网络是否重建 | 网桥名是否变化 | firewalld 是否受影响 |
|---|---|---|---|
| 容器重启 (docker restart) | ❌ | 不变 | ✅ 无影响 |
| 服务器重启 | ❌ | 不变 | ✅ 无影响 |
| docker-compose down + up (未固化) | ⚠️ 会 | ⚠️ 会变 | ❌ 通信中断 |
| docker-compose down + up (已固化) | ⚠️ 会 | ✅ 不变 | ✅ 无影响 |
经验总结
- Docker + firewalld 共存时,务必将 Docker 网桥加入 trusted zone,否则容器间通信会被拦截
- 不要依赖动态网桥名,在 docker-compose.yml 中通过
driver_opts.com.docker.network.bridge.name固化网桥名 - firewalld trusted zone 配置是持久的,只要网桥名不变,重启服务器也不会丢失
- 这个坑的本质是:Docker 网络的动态命名与 firewalld 基于接口名的静态规则之间的不匹配,固化网桥名是最简洁的解法
适用环境
- Alibaba Cloud Linux 3 / CentOS / RHEL 等使用 firewalld 的系统
- Docker Compose V2 编排的多容器应用
- 任何需要 firewalld 与 Docker 共存的场景