Lazy loaded image
网络
字数 5733阅读时长 15 分钟
2026-2-11
2026-2-11
type
Post
status
Published
date
Feb 11, 2026
slug
network
summary
tags
category
icon
password

docker网络

当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥。虚拟网桥的工作方式和物理交换机类似,作为容器的默认网关,负责容器之间及容器与宿主机的通信。默认 IP 地址:172.17.0.1/16。当启动一个容器时,Docker 会从 docker0 所属网段中分配一个 容器 IP(Container-IP)。容器的默认网关就是 docker0 网桥的 IP 地址,因为同一宿主机上的容器都连接到 docker0,所以它们可以直接通过 Container-IP 互相通信。
notion image
安装 Docker 以后,会默认创建三种网络:bridge、host、null,可以使用
命令查看

bridge模式

在 bridge(桥接)模式下,新创建的容器会自动连接到 Docker 创建的虚拟网桥上,默认是 docker0。附加到同一网桥上的网络接口之间可以通过二层转发机制实现互通。默认情况下,Docker 会为每个容器创建独立的网络命名空间,从而实现网络层面的相互隔离。每个容器都拥有自己独立的网络协议栈,包括:虚拟网卡、IP 地址、路由表、端口空间。
在 bridge 模式下,宿主机上的所有容器都会通过一对 veth 设备接入到 docker0 虚拟网桥上,可以通过执行 ip a 在宿主机中看到该网桥接口
notion image
容器 ip 为172.17.0.2,其中26: eth0@if27表示 eth0 是一块 veth 设备,其对端接口位于另一个网络命名空间中,对端接口的 ifindex 为 27。eth0 表示当前命名空间(容器内)看到的网卡名字。@if27这是一个 veth 对端引用,不是网卡名,表示对端接口的 ifindex = 27。这个对端接口存在于另一个 network namespace(通常是宿主机)。也就是说,容器里的 eth0,和宿主机上的某个 veth 接口是一对。用 Docker bridge 场景来还原整条链路,在 bridge 模式下,真实拓扑是:
查看桥接网络模式docker0虚拟网卡的详细信息,可以看到桥接模式的网关和IP
notion image
运行一个 nginx 容器时,如果没有通过 --net(或 --network)参数显式指定网络,Docker 会默认使用 bridge 网络模式
在桥接模式下,每个容器启动后,Docker 会为其分配一个独立的虚拟 IP 地址,该 IP 地址位于 Docker bridge 网络所使用的子网中。Docker 会自动为该容器创建一个独立的 network namespace,创建一对 veth 虚拟网卡,将其中一端放入容器的网络命名空间,将另一端接入宿主机上的默认 Linux bridge docker0
在桥接模式下, 容器自始至终使用的都是容器自身的虚拟网卡和虚拟IP,并不会占用宿主机的端口和IP。宿主机下 curl nginx容器IP,可以正常访问
下面我们在同一宿主机运行一个tomcat容器,在tomcat容器中,访问nginx容器
notion image
此时,先不退出tomcat容器时,打开一个新的终端窗口,在宿主机内执行 ip a 命令,可以看到两块虚拟网卡,分别对应nginx容器和tomcat容器。再次在宿主机通过 netstat -nalpt 查看宿主机的 80 端口并没有被占用。为什么在宿主机还能通过 curl 172.17.0.2 访问nginx容器呢?实际情况该 curl 命令此时访问的是容器内部的80端口。桥接模式下,宿主机和容器之间、同一宿主机下容器和容器之间的网络是互联互通的。非宿主机的其他主机,即使和宿主机是同一网段的局域网,也不能直接访问宿主内的容器。
在 bridge 网络模式下,外部主机无法直接访问宿主机内部容器所监听的服务端口。但可以通过端口映射的方式,间接访问容器内的服务。比如,当使用docker run -p 8000:8080命令启动容器时,Docker 会在宿主机上监听 8000 端口,并将该端口的流量转发到容器内部的 8080 端口。因此,外部主机可以通过 宿主机IP:8000 访问容器内运行在 8080 端口上的服务,外部主机不能直接访问容器的 8080 端口。这是因为在 bridge 模式下,容器处于独立的 network namespace 中,拥有独立的 IP 地址和端口空间,外部网络无法直接路由到该容器网络。端口映射的实现本质上依赖于宿主机的 iptables DNAT 规则,将访问宿主机指定端口的流量重定向至容器网络。
通过示意图,可以清晰的看到,docker容器在桥接模式下,会为每个容器分配单独的虚拟网卡、虚拟IP。然后再统一通过 docker0 虚拟网卡,统一和宿主机的 eth0 交互( 本例中,我的宿主网卡是ens33 )。注:虚拟网卡、虚拟IP,在容器启动后,分别通过 ip a 命令和 docker inspect 容器id ,可以查看。
notion image

host模式

host 网络模式下,容器不会拥有独立的网络命名空间,而是直接与宿主机共享同一个网络命名空间。因此,host 模式下的容器与宿主机共用 IP 地址、端口空间、路由表以及防火墙规则等网络资源。由于未创建独立的网络命名空间,host 模式下的容器不会创建 veth 虚拟网卡,也不会分配独立的虚拟 IP 地址,其网络接口与宿主机完全一致。需要注意的是,host 模式仅在网络层面与宿主机共享资源,容器在其他方面仍然保持隔离,例如:文件系统(Mount Namespace)、进程 ID 空间(PID Namespace)、IPC 资源等。
在端口使用方面,由于容器与宿主机共享同一端口空间,同一个端口在同一时间只能被一个进程占用。如果某个容器中的服务占用了宿主机的 80 端口,则宿主机上的其他服务以及后续启动的容器都无法再使用该端口,直到占用该端口的服务停止运行并释放端口资源。先用命令 ss -lnutp 或者 netstat -lnatp 验证一下是否有未知程序占用 80 端口,依次确保下面实验的准确性。
先后以host模式启动两个nginx服务,第一个nginx容器被启动后,会占用宿主机的80端口
执行 ip a 命令,可以发现 host 模式下的容器启动后,并不会创建新的网卡。桥接模式下的容器,会自动创建以 veth 开头的虚拟网卡。我们再来查看下nginx1容器的网络信息,可以发现 host 模式的容器,自身是没有任何网络资源信息的,都是空的,它用的一切网络资源都是宿主机的
notion image
这里我们也可以运行一个busybox容器进一步观察,可以发现容器内的网卡信息与物理机的网卡信息一样
notion image
并且可以与外网通讯
在这里插入图片描述
下面我们使用 curl 命令访问一下宿主机的 ip + 80 端口,发现可以直接访问。那么接下来我们再以 host 模式启动一个 nginx2 容器
查看 nginx2 状态,发现是 Exited,并没有真正启动
notion image
查看 nginx2 容器的启动日志可以发现,其启动失败的原因是 80 端口已被占用
notion image
至此,验证了在 host 网络模式下,容器与宿主机共享同一个 network namespace,因而也共享同一套端口空间。在这种模式下,端口资源遵循 先占先得 的原则:先启动并成功监听端口的进程(无论是宿主机上的服务,还是某个容器内的服务)可以正常工作,后续启动的容器或宿主机服务,若尝试使用同一端口,则会因端口冲突而启动失败。只有当占用该端口的进程停止运行并释放端口资源后,其他容器或服务才能重新使用该端口。因此,host 网络模式适合对网络性能要求较高、且端口规划清晰的场景,但不适合需要大量端口复用或多实例部署的服务。
下面我们再来开启另一台处于同一网段的虚拟主机,通过 curl 访问 host 网络模式下运行的 nginx 容器,可以发现外部主机能够直接访问宿主机内部的容器服务。这一现象在 bridge 网络模式下并不会出现:在 bridge 模式中,同一网段的外部主机无法直接访问容器,必须通过宿主机进行端口映射才能实现访问。之所以在 host 网络模式下,同一网段的主机可以直接访问宿主机内部的容器,是因为 host 模式下容器与宿主机共享同一个 network namespace。容器中的服务直接监听在宿主机的 IP 地址和端口上,因此,外部主机访问宿主机 IP 的过程,本质上就是在访问容器内的服务。
从网络视角来看,host 模式下给人的直观感觉是:宿主机就是容器,容器就是宿主机。除网络资源外,容器之间在其他资源维度上仍然保持隔离,例如:文件系统(Mount Namespace)、进程 ID 空间(PID Namespace)、IPC 资源等。因此,host 网络模式是一种以牺牲网络隔离性为代价,换取更高网络性能和更直观网络访问方式的运行模式。
notion image

none模式

none 网络模式模式下,Docker 不会为容器进行任何网络相关的自动配置,从而为用户提供最大程度的网络定制能力。使用 none 模式启动容器后:容器中仅存在 lo 回环接口,不分配 IP 地址,不配置路由表,不提供任何默认的网络通信能力。因此,容器在默认情况下无法与外部网络通信,无法与宿主机通信,无法与其他容器通信。从安全隔离角度来看,none 模式具备较高的隔离性,适用于对网络访问有严格限制的场景。
需要注意的是,none 模式并非不能使用网络,而是 Docker 不提供任何网络配置。如果有需要,用户可以通过手动方式(如创建 veth、配置路由、iptables 等)为容器构建完全自定义的网络拓扑。
下面我们以 --net=none 模式启动容器
查看宿主机网卡列表,看到宿主机的网卡列表没有任何变化,仅ens33物理网卡和docker0虚拟网卡,两个网卡
notion image
容器虽然启动了,但是并没有被分配任何端口
notion image
查看none网络模式下,容器的网络信息,可以发现网络资源信息都是空的
notion image
none网络模式示意图
notion image

container模式

container 网络模式用于让多个容器共享同一个网络命名空间。在该模式下,通常先启动一个容器,随后启动的容器在启动时通过 --network container:<容器名或ID> 指定网络模式。这些后续创建的容器将与被指定的容器共享同一套网络资源,包括:网络命名空间、IP 地址、端口、路由表、iptables 规则等。因此,新创建的容器不会拥有自己的虚拟网卡(veth),不会分配独立的 IP 地址,使用的完全是目标容器的网络配置。一旦该容器停止,网络命名空间被销毁,其他共享容器将失去网络功能。
需要注意的是仅网络资源被共享,进程、文件系统、PID、用户等其他资源仍然彼此隔离。从外部访问角度看,多个容器在网络层面表现为同一个容器,对外暴露端口仍需通过该网络命名空间对应的容器进行端口映射。下面我们来模拟 container 网络模式案例,先以 bridge 网络模式启动一个 nginx 容器
下面我们再来以 container 模式启动一个 busybox 容器,--net=container 后面直接跟冒号,冒号后面是它所依靠的以桥接方式启动的指定容器,即为container:nginx,其中 nginx 是上一步以 bridge 方式启动的容器
注意:该模式不能使用 -p 参数,container 模式的 ip 和端口是不受 container 模式的容器自身控制,它的 ip 和端口,相当于完全委托给第一个以桥接方式启动的容器了。如果你不小心带了 -p 参数,你将看到docker: Error response from daemon: conflicting options: port publishing and the container type network mode这个错误。
查看网卡列表信息,可以看到没有因为启动 busybox 容器而增加虚拟网卡
notion image
分别查看两个容器的网络IP信息,可以发现,第一个以桥接方式启动的容器的网络信息 ip 端口 网关都有,而第二个以 container 模式启动容器的网络信息都是空的
notion image
进入到 busybox 容器,发现使用的完全是目标容器的网络配置
notion image
container 网络模式如果第一个容器停止,网络命名空间就会被销毁,共享它网络的容器会失去网络,容器进程本身不一定立刻退出,但网络功能基本不可用。因为第二个容器并没有自己的网络命名空间,它只是进入了容器一的 network namespace,容器一是 network namespace 的拥有者,容器一停止表示 namespace 被释放,所有依赖这个 namespace 的容器网络立即失效。为了更好的观察,我这里启动一个tomcat容器
此时,使用curl命令访问nginx和tomcat容器服务,访问都是正常的
notion image
查看tomcat容器的网络IP信息,发现也都是空的
notion image
查看 tomcat 容器,发现使用的完全是目标容器的网络配置
notion image
现在 busybox 容器和 tomcat 容器网络服务一切正常
notion image
现在我们把nginx容器服务停止掉
此时在 busybox 容器和 tomcat 容器执行 ping / curl 都会失败,端口监听也失效,进程还在,但 namespace 已经没了。说白了就是进程活着,网络死了
notion image
container网络模式图解
notion image

自定义网络模式

在学习自定义网络模式前,先了解一下 docker network 几个常用的命令
下面我们来创建一个 bridge 网络。自定义网络时,不指定网络模式,默认就是bridge桥接模式
notion image
创建自定义 bridge 网络时,Docker 会在宿主机上创建一个新的 Linux bridge 设备(br-xxxx),并为其分配独立的子网和网关。连接到该网络的容器通过 veth 接口挂载到该 bridge 上,实现二层转发。下面我们来使用 --subnet 选项指定子网网段,不能与其他网卡的网段重叠,本例的 mynet 就指定为 172.25.0.0/16。bridge网络只能指定一个子网,而overlay网络支持多个子网。通过命令 docker inspect 命令,查找 “Driver”: “overlay2”,可以看到驱动模式是overlay2
下面我们来创建三个容器
然后再额外给 nginx2 容器添加自定义的 mynet 网络模式
查看这三个容器的网络情况: nginx1 容器的网络模式是默认的bridge,网卡使用的是docker0,IP为172.17.0.2 nginx2 容器的网络模式是bridge和自定义的mynet网络,IP分别是172.17.0.3、172.25.0.2 nginx2 容器的网络模式是自定义的mynet网络,该IP为172.25.3.3,运行容器时指定的IP
notion image
默认 bridge 网络(docker0)不提供内置 DNS 服务,因此容器之间通常只能通过 IP 地址进行访问。自定义 bridge 网络则内置 Docker DNS 服务,支持通过容器名或别名进行互相访问。一个容器可以同时连接多个 bridge 网络,因此可以拥有多个 IP 地址和多块 veth 设备。在同一个自定义 bridge 网络中的容器,可以通过容器名直接通信;而在默认 bridge 网络中,则通常需要使用 IP 地址。
notion image
nginx1 容器使用的是默认的bridge模式。nginx2 容器启动后在默认bridge模式基础上,又单独多指定了自定义的mynet网络模式,此时它同时拥有2个网络模式。nginx3 网络模式为mynet自定义网络模式。说明bridge网络模式之间的容器,只能通过IP相互访问;自定义网络模式可以通过容器别名相互访问。
下面我们将 nginx2 容器的自定义网络模式 mynet 移除掉
移除后,nginx2 容器只剩下了默认的网络模式bridge桥接模式
notion image
此时就不能再通过容器别名 ping 通 nginx3 容器了,因为此时的 nginx2 容器和 nginx1 容器没有本质区别,都是使用的 docker0 网卡的bridge桥接模式。此时 nginx2 容器和 nginx3 容器 两者处于不同网段,使用 ip 也无法 ping 通。最后,执行 docker network rm 命令移除自定义网络模式 mynet。至此,相信你对docker的自定义网络模式,已经有了深入了解,内容虽然不难,比较容易理解,要去理解记忆、动手实践一下哦,图文已经总结的很全面,希望对你有所帮助!
至此,我花费了不少时间和精力,终于把 Docker 的 5 种网络模式系统梳理了一遍。对我来说,这是一个阶段性的总结。但对你来说,也许正是学习的开始。建议你跟着文中的步骤,亲自做一遍实验,多动手、多记录。在理解原理的基础上消化吸收,真正变成自己的知识。如果这篇内容对你有帮助,也欢迎点个赞支持一下,这会是我继续输出优质内容的最大动力。
 
上一篇
操作系统-cpu
下一篇
go-数据类型