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 互相通信。

安装 Docker 以后,会默认创建三种网络:bridge、host、null,可以使用
命令查看
bridge模式
在 bridge(桥接)模式下,新创建的容器会自动连接到 Docker 创建的虚拟网桥上,默认是 docker0。附加到同一网桥上的网络接口之间可以通过二层转发机制实现互通。默认情况下,Docker 会为每个容器创建独立的网络命名空间,从而实现网络层面的相互隔离。每个容器都拥有自己独立的网络协议栈,包括:虚拟网卡、IP 地址、路由表、端口空间。
在 bridge 模式下,宿主机上的所有容器都会通过一对 veth 设备接入到 docker0 虚拟网桥上,可以通过执行
ip a 在宿主机中看到该网桥接口
容器 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

运行一个 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容器

此时,先不退出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 ,可以查看。

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 模式的容器,自身是没有任何网络资源信息的,都是空的,它用的一切网络资源都是宿主机的
这里我们也可以运行一个busybox容器进一步观察,可以发现容器内的网卡信息与物理机的网卡信息一样

并且可以与外网通讯

下面我们使用 curl 命令访问一下宿主机的 ip + 80 端口,发现可以直接访问。那么接下来我们再以 host 模式启动一个 nginx2 容器
查看 nginx2 状态,发现是 Exited,并没有真正启动

查看 nginx2 容器的启动日志可以发现,其启动失败的原因是 80 端口已被占用

至此,验证了在 host 网络模式下,容器与宿主机共享同一个 network namespace,因而也共享同一套端口空间。在这种模式下,端口资源遵循 先占先得 的原则:先启动并成功监听端口的进程(无论是宿主机上的服务,还是某个容器内的服务)可以正常工作,后续启动的容器或宿主机服务,若尝试使用同一端口,则会因端口冲突而启动失败。只有当占用该端口的进程停止运行并释放端口资源后,其他容器或服务才能重新使用该端口。因此,host 网络模式适合对网络性能要求较高、且端口规划清晰的场景,但不适合需要大量端口复用或多实例部署的服务。
下面我们再来开启另一台处于同一网段的虚拟主机,通过 curl 访问 host 网络模式下运行的 nginx 容器,可以发现外部主机能够直接访问宿主机内部的容器服务。这一现象在 bridge 网络模式下并不会出现:在 bridge 模式中,同一网段的外部主机无法直接访问容器,必须通过宿主机进行端口映射才能实现访问。之所以在 host 网络模式下,同一网段的主机可以直接访问宿主机内部的容器,是因为 host 模式下容器与宿主机共享同一个 network namespace。容器中的服务直接监听在宿主机的 IP 地址和端口上,因此,外部主机访问宿主机 IP 的过程,本质上就是在访问容器内的服务。
从网络视角来看,host 模式下给人的直观感觉是:宿主机就是容器,容器就是宿主机。除网络资源外,容器之间在其他资源维度上仍然保持隔离,例如:文件系统(Mount Namespace)、进程 ID 空间(PID Namespace)、IPC 资源等。因此,host 网络模式是一种以牺牲网络隔离性为代价,换取更高网络性能和更直观网络访问方式的运行模式。

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

容器虽然启动了,但是并没有被分配任何端口

查看none网络模式下,容器的网络信息,可以发现网络资源信息都是空的

none网络模式示意图

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 容器而增加虚拟网卡

分别查看两个容器的网络IP信息,可以发现,第一个以桥接方式启动的容器的网络信息 ip 端口 网关都有,而第二个以 container 模式启动容器的网络信息都是空的

进入到 busybox 容器,发现使用的完全是目标容器的网络配置

container 网络模式如果第一个容器停止,网络命名空间就会被销毁,共享它网络的容器会失去网络,容器进程本身不一定立刻退出,但网络功能基本不可用。因为第二个容器并没有自己的网络命名空间,它只是进入了容器一的 network namespace,容器一是 network namespace 的拥有者,容器一停止表示 namespace 被释放,所有依赖这个 namespace 的容器网络立即失效。为了更好的观察,我这里启动一个tomcat容器
此时,使用curl命令访问nginx和tomcat容器服务,访问都是正常的

查看tomcat容器的网络IP信息,发现也都是空的

查看 tomcat 容器,发现使用的完全是目标容器的网络配置

现在 busybox 容器和 tomcat 容器网络服务一切正常

现在我们把nginx容器服务停止掉
此时在 busybox 容器和 tomcat 容器执行 ping / curl 都会失败,端口监听也失效,进程还在,但 namespace 已经没了。说白了就是进程活着,网络死了

container网络模式图解

自定义网络模式
在学习自定义网络模式前,先了解一下 docker network 几个常用的命令
下面我们来创建一个 bridge 网络。自定义网络时,不指定网络模式,默认就是bridge桥接模式

创建自定义 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

默认 bridge 网络(docker0)不提供内置 DNS 服务,因此容器之间通常只能通过 IP 地址进行访问。自定义 bridge 网络则内置 Docker DNS 服务,支持通过容器名或别名进行互相访问。一个容器可以同时连接多个 bridge 网络,因此可以拥有多个 IP 地址和多块 veth 设备。在同一个自定义 bridge 网络中的容器,可以通过容器名直接通信;而在默认 bridge 网络中,则通常需要使用 IP 地址。

nginx1 容器使用的是默认的bridge模式。nginx2 容器启动后在默认bridge模式基础上,又单独多指定了自定义的mynet网络模式,此时它同时拥有2个网络模式。nginx3 网络模式为mynet自定义网络模式。说明bridge网络模式之间的容器,只能通过IP相互访问;自定义网络模式可以通过容器别名相互访问。
下面我们将 nginx2 容器的自定义网络模式 mynet 移除掉
移除后,nginx2 容器只剩下了默认的网络模式bridge桥接模式

此时就不能再通过容器别名 ping 通 nginx3 容器了,因为此时的 nginx2 容器和 nginx1 容器没有本质区别,都是使用的 docker0 网卡的bridge桥接模式。此时 nginx2 容器和 nginx3 容器 两者处于不同网段,使用 ip 也无法 ping 通。最后,执行
docker network rm 命令移除自定义网络模式 mynet。至此,相信你对docker的自定义网络模式,已经有了深入了解,内容虽然不难,比较容易理解,要去理解记忆、动手实践一下哦,图文已经总结的很全面,希望对你有所帮助!
至此,我花费了不少时间和精力,终于把 Docker 的 5 种网络模式系统梳理了一遍。对我来说,这是一个阶段性的总结。但对你来说,也许正是学习的开始。建议你跟着文中的步骤,亲自做一遍实验,多动手、多记录。在理解原理的基础上消化吸收,真正变成自己的知识。如果这篇内容对你有帮助,也欢迎点个赞支持一下,这会是我继续输出优质内容的最大动力。
- 链接:www.qianshuai.cn/article/network
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。







