共计 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_HOST为127.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网络、端口精确映射、服务发现)只有在桥接模式下才能实现。主机模式不是”性能更好但安全性略低”的选择,而是根本无法实现本方案安全设计的选择。
性能差异在这个量级的应用中完全不存在,而安全隔离的差异是”有”和”无”的区别。