← 全部笔记

Docker · 5 容器网络

host / none 网络模式

bridge 接入独立网络;host 共用宿主机网络;none 只留下容器自己的回环。

约 15 分钟 · 截至 2026-11-03,Docker Engine 29.x · 实验未实测

bridge

bridge:转发到容器网络 宿主机端口 8080 经发布规则、网桥和 veth 虚拟网线转发到独立网络命名空间里的容器端口 80。 宿主机网络 :8080 → 发布到 :80 转发 网桥 veth 容器 IP · 应用 :80

独立网络命名空间;可用 -p 发布端口。

host

host:应用直接监听宿主机端口 容器进程和宿主机进程位于同一个网络命名空间;请求直接到应用端口 80,没有独立容器 IP 和端口转发。 宿主机与容器共用网络 请求宿主机 :80 直接到达 容器中的应用 :80 没有独立容器 IP

共用网络命名空间;-p 被忽略。

none

none:容器里只保留回环 独立容器网络中只有 lo 回环设备。没有连接宿主机的虚拟网线,外部网络不能沿网卡进入。 宿主机网络 外部网络 无连接 容器自己的网络 lo · 127.0.0.1

独立网络命名空间;没有对外网卡。

图 1 Linux 上,三种模式的关键差别是网络边界与连接方式;端口为示意配置。[1–3]

先看边界

先问网络归谁

网络命名空间(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)bridgehostnone
独立网络命名空间有共用宿主机有
独立容器 IP默认分配不分配只有回环地址
127.0.0.1 指向容器自己宿主机共用网络容器自己
宿主机端口入口通常用 -p 发布应用直接监听无对外网卡

host 的机制

host 忽略 -p

--network host 下,应用监听哪个端口,就使用共用网络里的那个端口。-p 8080:80 不会把应用改到 8080;应用仍需监听 80。[2]

host 下端口不经过映射 启动 host 模式后,发布参数被忽略。应用在共用网络中监听 80,请求 80 直接到达;8080 不会自动产生入口。再次在同一地址监听 80 会产生冲突。 Linux 宿主机网络 容器应用进入共用网络 -p 8080:80 被忽略 监听 :80 请求 :80 直接到达 :8080无映射入口 第二个同地址 :80 监听 → 冲突
  1. 启动 host 容器:它与 Linux 宿主机共用网络命名空间。
  2. Docker 忽略 -p 8080:80 并发出警告。先猜:应用监听 80 后,应该访问 80 还是 8080?
  3. 应用在共用网络中绑定 80。绑定就是向系统申请接收某个本地地址、端口上的请求。
  4. 访问对应宿主机地址的 80,请求直接到应用,无需端口转发。
  5. 8080 没有因为 -p 新增入口;如果原来已有服务,访问到的会是原来的服务。
  6. 另一个进程若按普通独占方式绑定同协议、同地址的 80,会冲突;改应用监听端口,或改用 bridge 发布。
图 2 host 的端口由应用监听配置决定;改 -p 不能解决监听冲突。示意假设无特殊端口复用。[2]

下面是 Docker 官方文档的警告原文,并非本环境实测输出:

WARNING: Published ports are discarded when using host network mode

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 内部可以通信,外部无网络连接 同一容器内,进程 A 可以通过 127.0.0.1 连接进程 B。独立网络命名空间没有对外网卡,因此外网方向被阻断。 none 容器的网络命名空间 进程 A 进程 B 127.0.0.1 lo:仅在此边界内传递 无对外网卡
图 3 none 切断默认对外网络连接,容器内部的 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]

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

你也可把第二条的 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,宿主机入口仍需不同。

一个校验程序只读取已挂载的本地文件,不应访问外部网络。哪种配置最符合这个需求?

-p 控制发布入口;不发布不等于禁止出站连接。

host 让应用共用宿主机网络,减少了网络隔离。

none 默认只保留容器内部的回环,符合这个离线步骤的网络需求。它并不替代文件权限、挂载范围和其他安全控制。

来源

截至 2026-11-03 核对;正文面向 Docker Engine 29.x。命令全部未实测,引用的终端输出已标注官方来源。

  1. Docker Docs:Bridge network driver — 默认连接、出站地址转换、发布端口和虚拟网络管理。
  2. Docker Docs:Host network driver — 共用网络、忽略 -p 的警告、端口限制、Desktop 支持与限制。
  3. Docker Docs:None network driver — 仅有 lo、Alpine 命令及输出、IPv6 回环限制。
  4. Docker CLI:docker container run — 镜像拉取策略、--rm 和 --network 参数。
  5. Python 文档:http.server 命令行接口 — 实验的端口参数及 --bind 限制监听地址。