Docker WordPress 建站答疑(二):为什么各容器的网络模式不推荐使用 Host(主机) 而用 Bridge(桥接)模式

20次阅读
没有评论

共计 3435 个字符,预计需要花费 9 分钟才能阅读完成。

本文内容在完整版教程 Docker WordPress 建站指南:从零到生产级部署 基础上进行讨论

一、两种模式的本质区别

主机模式

┌─────────────────────────────────────────────────┐
│                  宿主机                          │
│                                                 │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐          │
│  │  Nginx  │  │   WP    │  │ MariaDB │          │
│  │  :80    │  │  :80 ❌ │  │  :3306  │         │
│  │  :443   │  │  冲突!   │  │  直接暴露│         │
│  └─────────┘  └─────────┘  └─────────┘          │
│                                                 │
│  所有容器共享同一个网络命名空间                    │
│  所有端口直接绑定在宿主机网卡上                    │
│  没有容器间隔离,没有端口映射                      │
└─────────────────────────────────────────────────┘

桥接模式(本方案)

┌─────────────────────────────────────────────────────────┐
│                      宿主机                              │
│                                                         │
│  ┌─── web 网络 ──────────────────────────────────────┐  │
│  │  Nginx ──────────────► WordPress                  │  │
│  │  (:80/:443 映射到宿主机)    (:80 仅内网可见)        │  │
│  └───────────────────────────────────────────────────┘  │
│                                                         │
│  ┌─── backend 网络 (internal: true) ─────────────────┐  │
│  │  WordPress ──► MariaDB ◄── phpMyAdmin             │  │
│  │  (:3306 仅内网)  (:3306 仅内网)  (:80 仅内网)      │  │
│  │  ⛔ 无外网出口,外部不可达                          │  │
│  └───────────────────────────────────────────────────┘  │
│                                                         │
│  ┌─── admin 网络 ────────────────────────────────────┐  │
│  │  Nginx ──────────────► phpMyAdmin                 │  │
│  └───────────────────────────────────────────────────┘  │
│                                                         │
│  每个容器有独立网络命名空间                               │
│  端口映射精确控制暴露范围                                 │
└─────────────────────────────────────────────────────────┘

二、不推荐主机模式的核心理由

2.1 安全隔离彻底丧失(最致命)

本方案的安全架构完全依赖桥接网络的隔离能力:

networks:
  backend:
    internal: true    # ← host 模式下此配置无意义

如果用主机模式:

组件 桥接模式 主机模式
MariaDB :3306 仅 backend 网络可达,公网不可见 直接绑定宿主机 3306,全网可扫描
phpMyAdmin :80 仅 admin/backend 网络 + 127.0.0.1:8098 直接绑定宿主机 80 或需手动改端口
WordPress :80 仅 web 网络(Nginx 反代) 直接绑定宿主机,绕过 Nginx 防护
网络分段 ✅ 三条网络互不干扰 ❌ 不存在

一句话:主机模式下,internal: true、网络分段、端口映射全部失效,等于把数据库和管理工具裸奔在公网上。

2.2 端口冲突不可避免

本方案有四个容器需要监听网络端口:

容器 容器内监听 宿主机映射
Nginx :80, :443 80, 443
WordPress (Apache) :80 不映射(仅 web 网络)
MariaDB :3306 不映射(仅 backend)
phpMyAdmin :80 127.0.0.1:8098

主机模式下的冲突:

Nginx 要监听 :80
WordPress (Apache) 也要监听 :80    ← 冲突!
phpMyAdmin (Apache) 也要监听 :80   ← 冲突!

你必须手动修改每个服务的监听端口:

  • WordPress 改成 :8080
  • phpMyAdmin 改成 :8081
  • 然后修改 Nginx upstream 指向这些端口
  • 然后修改 WordPress 的 WORDPRESS_DB_HOST127.0.0.1:3306
  • 然后确保宿主机防火墙规则正确……

每加一个容器,就多一次端口规划。 桥接模式下,容器内部都用自己的默认端口,互不干扰。

2.3 服务发现失效

桥接模式下,Docker 内置 DNS(127.0.0.11)自动解析容器名:

# Nginx 配置中直接用容器名
upstream wordpress_backend {
    server wordpress:80;    # ← Docker DNS 自动解析
}

# WordPress 连接数据库
WORDPRESS_DB_HOST: mysql:3306    # ← 容器名即主机名

主机模式下:

  • 没有 Docker DNS
  • 必须用 127.0.0.1 或宿主机 IP
  • 如果宿主机 IP 变了,所有配置都要改
  • 容器名不再有意义,退化为”手动管理 IP + 端口”

2.4 端口映射的精确控制

桥接模式下,只有你显式声明的端口才对外暴露:

nginx:
  ports:
    - "80:80/tcp"
    - "443:443/tcp"
    - "443:443/udp"

dbweb:
  ports:
    - "127.0.0.1:8098:80"    # 仅本机可达

MariaDB 没有 ports 声明 → 宿主机上没有任何端口映射到它。

主机模式下: 容器监听什么端口,宿主机就暴露什么端口。你无法”不暴露”某个端口,只能靠宿主机防火墙(iptables/ufw)额外拦截——又多了一层需要维护的配置。

2.5 Docker Compose 编排特性失效

特性 桥接模式 主机模式
ports 映射 ✅ 正常工作 ❌ 无意义(已共享宿主机网络)
networks 定义 ✅ 多网络隔离 ❌ 无意义
internal: true ✅ 禁止外网 ❌ 无意义
expose ✅ 声明性文档 ❌ 无意义
depends_on + 健康检查 ✅ 正常 ✅ 正常(但网络层面无隔离)
容器名 DNS ✅ 自动 ❌ 不可用

2.6 故障隔离

桥接模式:

  • MariaDB 崩溃 → 仅 backend 网络受影响
  • Nginx 配置错误 → 仅 80/443 不可用,数据库仍正常
  • 一个容器的网络异常不会波及其他容器

主机模式:

  • 所有容器共享宿主机网络栈
  • 一个容器错误地绑定了 0.0.0.0:3306,另一个容器可能连不上
  • 容器内的 iptables 规则(如果有的话)可能影响宿主机

2.7 可移植性

桥接模式的 docker-compose.yml 是自包含的:

# 在任何一台装了 Docker 的机器上
docker compose up -d
# 完事。端口、网络、DNS 全部自动处理。

主机模式依赖宿主机环境:

  • 端口 80 是否被占用?
  • 端口 3306 是否被宿主机上的其他 MySQL 占用?
  • 防火墙规则是否配置正确?
  • 换一台机器,所有假设可能都不成立。

三、性能差异:可以忽略

这是主机模式唯一的”优势”:

指标 桥接模式 主机模式
网络延迟 +~0.05ms(经过 veth + bridge) 原生
吞吐量 ~99% 原生 100% 原生
连接数开销 每个容器一个 veth pair

对于 WordPress 博客:

  • 请求瓶颈在 PHP 执行(几十到几百毫秒)和数据库查询(几到几十毫秒)
  • 网络层的 0.05ms 差异完全不可感知
  • 即使 1000 QPS,网络开销也不到总延迟的 0.1%

只有以下场景才需要主机模式的性能:

  • 高频交易(微秒级延迟敏感)
  • DPDK / SR-IOV 网络加速
  • 每秒百万级连接的网络设备

四、那什么时候可以用主机模式?

场景 是否适合主机模式 原因
单容器、无安全隔离需求 ⚠️ 可以 如纯计算任务
需要大量动态端口(FTP 被动模式) ✅ 适合 桥接模式端口映射困难
网络监控/抓包工具 ✅ 适合 需要看到宿主机全部流量
多容器协作、有安全隔离需求 ❌ 不适合 本方案场景
数据库容器 ❌ 绝不 端口直接暴露
管理工具(phpMyAdmin) ❌ 绝不 需要精确控制访问来源

五、总结

考量维度 桥接模式 主机模式
网络隔离 ✅ 三网络分段 ❌ 无
数据库保护 ✅ internal 网络 ❌ 端口裸奔
端口冲突 ✅ 无(各自命名空间) ❌ 必须手动规划
服务发现 ✅ 容器名 DNS ❌ 手动 IP/端口
精确暴露控制 ✅ 仅声明的端口 ❌ 全部暴露
可移植性 ✅ 开箱即用 ❌ 依赖宿主机
故障隔离 ✅ 互不影响 ❌ 共享网络栈
性能 99%+ 100%
配置复杂度 低(声明式) 高(手动端口+防火墙)

本方案选择桥接模式的根本原因:

安全架构(internal 网络、端口精确映射、服务发现)只有在桥接模式下才能实现。主机模式不是”性能更好但安全性略低”的选择,而是根本无法实现本方案安全设计的选择。

性能差异在这个量级的应用中完全不存在,而安全隔离的差异是”有”和”无”的区别。

正文完
 0
评论(没有评论)