先看边界
先问网络归谁
网络命名空间(network namespace)是一组独立的网卡、IP、路由和端口视图。图中的虚线表示这个边界。回环设备(loopback,lo)让同一网络命名空间内的进程通过 127.0.0.1 通信。
bridge 通过网桥和 veth(成对的虚拟网卡,像一根虚拟网线)连接容器网络。host 共用 Linux 宿主机的网络视图;none 建立独立视图,但只保留回环设备。[1] [2] [3]
这里的宿主机指 Docker 守护进程所在的 Linux 主机。正文以本机常规 Linux Engine 为准;远程 Docker 和 Docker Desktop 要分清命令行所在机器与引擎所在环境。可先回顾客户端与守护进程、容器的隔离边界。
宿主机有一个只监听 127.0.0.1 的服务。bridge 和 host 容器分别访问 127.0.0.1,会到同一个地方吗?先写出两个地址各指向谁。
bridge 容器访问自己的回环,无法用这个地址到达宿主机服务。Linux host 容器访问宿主机的回环,因为两者共用网络命名空间。none 的回环也只属于容器自己。
| 判断项(Linux) | bridge | host | none |
|---|---|---|---|
| 独立网络命名空间 | 有 | 共用宿主机 | 有 |
| 独立容器 IP | 默认分配 | 不分配 | 只有回环地址 |
| 127.0.0.1 指向 | 容器自己 | 宿主机共用网络 | 容器自己 |
| 宿主机端口入口 | 通常用 -p 发布 | 应用直接监听 | 无对外网卡 |
host 的机制
host 忽略 -p
--network host 下,应用监听哪个端口,就使用共用网络里的那个端口。-p 8080:80 不会把应用改到 8080;应用仍需监听 80。[2]
- 启动 host 容器:它与 Linux 宿主机共用网络命名空间。
- Docker 忽略
-p 8080:80并发出警告。先猜:应用监听 80 后,应该访问 80 还是 8080? - 应用在共用网络中绑定 80。绑定就是向系统申请接收某个本地地址、端口上的请求。
- 访问对应宿主机地址的 80,请求直接到应用,无需端口转发。
- 8080 没有因为
-p新增入口;如果原来已有服务,访问到的会是原来的服务。 - 另一个进程若按普通独占方式绑定同协议、同地址的 80,会冲突;改应用监听端口,或改用 bridge 发布。
-p 不能解决监听冲突。示意假设无特殊端口复用。[2]下面是 Docker 官方文档的警告原文,并非本环境实测输出:
host 可省掉地址转换(NAT,即改写数据包地址或端口)及每端口代理的开销,适合确有大量端口需求的应用。是否更快要测量;代价是网络隔离减少。它不会自动改变文件系统、进程等其他隔离设置。[2]
Linux 上,服务监听 0.0.0.0:9000,以 --network host -p 19000:9000 启动。假设端口空闲、防火墙允许,宿主机上的客户端应访问哪个端口?
host 会忽略发布参数。找应用实际监听的端口。
没有端口转发,也不会复制一个监听端口。
答案是 9000。0.0.0.0 表示监听所有本地 IPv4 地址;host 下这些地址属于共用的宿主机网络。19000 不会因 -p 被占用。
Docker Desktop 的 host 有何不同?
截至 2026-11-03,官方文档列出 Docker Desktop 4.34 及以后支持 host,登录 Docker Desktop 后,需在 Settings → Resources → Network 勾选 Enable host networking,并应用、重启。仅支持 Linux 容器;Windows 容器不支持。[2]
Desktop 的实现工作在传输层(第 4 层),支持 TCP/UDP 的双向访问。它不等于原生 Linux 共用全部网卡:容器不能直接访问宿主机接口、绑定宿主机特定网卡 IP;低于 TCP/UDP 的协议不受此功能支持。
增强容器隔离(Enhanced Container Isolation,额外限制容器与宿主机接触的功能)启用时不能用 host。不要用 ping 或“容器能否看到宿主机网卡”来判断 Desktop 的 host 是否成功;按官方 TCP/UDP 示例验证。下面 host 实验的基线是本机 Linux Engine。
none 的机制
none 只留回环
--network none 创建的容器默认只有 lo,没有通向网桥或外网的网卡。它仍能执行程序,也能让容器内的进程通过 IPv4 回环通信。[3]
常见用途是处理已在本地的数据:例如离线转换文件、计算校验值,或测试程序在断网时的行为。需要的输入可由前面学过的数据卷或绑定挂载提供。挂载的文件、设备和权限仍需单独控制。
一个离线转换程序使用 none,但启动时还要从网站下载字体。它能直接完成任务吗?你会怎样准备运行所需的数据?
不能按这个流程完成。none 容器没有对外网卡;应提前把字体放进镜像或准备为本地输入,再运行离线步骤。none 只控制容器网络,不会替你准备依赖,也不是完整的安全沙箱。
“只剩回环”有哪些边界?
截至 2026-11-03,官方说明 none 默认不配置 IPv6 回环地址;不要把 ::1 与 IPv4 的 127.0.0.1 混为一谈。[3]
这里描述 Docker 默认创建的网络。若额外授予修改网络的能力、挂入宿主机服务的 socket,或人为接入其他通道,隔离条件就变了。本页实验不需要这些设置。
动手验证
用命令验边界
编写环境没有 Docker。下面提供可运行命令和预期现象,供你验证;维护者可补实测输出。请在本机 Linux Docker Engine 29.x 上操作,并确认 Docker 上下文指向本机。
镜像首次拉取需要宿主机联网;none 约束启动后的容器网络,不阻止守护进程拉取镜像。实验会下载镜像并临时创建容器;bridge 由 Docker 管理虚拟网络及相关防火墙规则。无需 --privileged,不手动改 iptables。[4] [1]
实验 A:观察 none 的设备
先拉取镜像,避免把拉取失败误判为 none 的行为。alpine:latest 沿用官方 none 示例,标签内容会变化,设备编号与字段可能不同。
docker pull alpine:latest
docker run --rm --network none alpine:latest ip link show
docker run --rm --network none alpine:latest ip addr show
docker run --rm --network none alpine:latest ip route show
预期(未实测):设备列表只含 lo;地址列表包含 127.0.0.1/8;默认配置下 IPv4 路由列表为空。三个命令各创建一个容器,退出后由 --rm 删除。
官方文档中 ip link show 的输出原文如下,仅作识别设备的参考:[3]
你也可把第二条的 none 改为 bridge 再运行:默认配置下会多出连接网桥的网卡。只看程序退出并不能证明能联网;要看接口和路由。
实验 B:确认 host 忽略映射
本实验用 Python 内置 HTTP 服务。[5]终端 A、B 都开在同一台 Linux 宿主机。需要宿主机已有 ss 和 curl;先用 ss 检查 18080、18081 没有监听者,有则先换两个空闲端口。
# 终端 A:先确认下列两个端口没有监听行
ss -ltn '( sport = :18080 or sport = :18081 )'
docker pull python:3-alpine
# 前台运行,故意带上会被忽略的 -p
docker run --rm --name host-none-web --network host \
-p 127.0.0.1:18081:18080 \
python:3-alpine python -m http.server 18080 --bind 127.0.0.1
宿主机影响:服务会临时占用宿主机 IPv4 回环的 18080。--bind 127.0.0.1 限制本实验的监听地址;host 下不能靠被忽略的 -p 127.0.0.1:… 限制暴露范围。
# 终端 B:等终端 A 的服务启动后再执行
curl --noproxy '*' --connect-timeout 2 -I http://127.0.0.1:18080/
curl --noproxy '*' --connect-timeout 2 -I http://127.0.0.1:18081/
# 清理;--rm 会随后删除已停止的实验容器
docker stop host-none-web
预期(未实测):终端 A 出现前述官方 host 警告;18080 收到 HTTP 响应头,18081 连接失败。服务启动失败时先排查端口冲突;18081 意外可达时检查是否有其他服务。不要把宿主机其他服务的响应当成映射成功。
也可在终端 A 按 Ctrl+C 停止服务。镜像会保留在本机,容器随退出删除。不要在另有同名容器时照抄名称。
实验 B 保持 host 模式,要让客户端改为访问 18082,应把 Python 的 http.server 后面的监听端口改为多少?
应用监听端口:
填 18082,并先检查它空闲。host 下入口跟着应用监听端口改变;只改 -p 不会改变入口。
迁移与回顾
按需求选模式
普通应用先用自定义 bridge 连接服务。确认必须共用宿主机网络时再用 host;明确不需要外部网络的步骤可用 none。不要把“去掉 -p”当成断网:bridge 默认仍能向外发起连接。[1]
同一台 Linux 主机要跑两个都默认监听 80 的 Web 服务。用自己的话解释:为什么 host 下只改 -p 不够?怎样用 bridge 保留两个应用的监听配置?
host 共用网络,同一地址的普通独占监听会冲突;两个 -p 都被忽略。改用两个 bridge 容器,它们各有独立端口空间,再用不同宿主机端口发布到各自的 80。
- 说明 host 的端口空间共用,发布参数被忽略。
- 说明 bridge 可让两个容器各自监听 80,宿主机入口仍需不同。
- bridge:独立网络,按需发布端口。
- host:共用网络,入口与冲突看应用监听。
- none:只留回环,依赖和输入提前备齐。
- Desktop:先启用,再按 TCP/UDP 的能力边界验证。
一个校验程序只读取已挂载的本地文件,不应访问外部网络。哪种配置最符合这个需求?
-p 控制发布入口;不发布不等于禁止出站连接。
host 让应用共用宿主机网络,减少了网络隔离。
none 默认只保留容器内部的回环,符合这个离线步骤的网络需求。它并不替代文件权限、挂载范围和其他安全控制。
来源
截至 2026-11-03 核对;正文面向 Docker Engine 29.x。命令全部未实测,引用的终端输出已标注官方来源。
- Docker Docs:Bridge network driver — 默认连接、出站地址转换、发布端口和虚拟网络管理。
- Docker Docs:Host network driver — 共用网络、忽略 -p 的警告、端口限制、Desktop 支持与限制。
- Docker Docs:None network driver — 仅有 lo、Alpine 命令及输出、IPv6 回环限制。
- Docker CLI:docker container run — 镜像拉取策略、--rm 和 --network 参数。
- Python 文档:http.server 命令行接口 — 实验的端口参数及 --bind 限制监听地址。