☰
Docker 网络深度梳理:从基础使用到底层原理
2026/10/7 8:39:18 网站建设 项目流程

核心痛点:为什么 Docker 需要网络?

实际项目通常不是一个容器,而是多个容器共同工作(如:用户 -> Nginx -> 后端服务 -> MySQL/Redis)。Docker 网络主要解决三个核心问题:

  1. 容器自己怎么联网?(访问互联网)

  2. 外部怎么访问容器?(端口映射)

  3. 容器之间怎么通信?(跨容器互联)


一、 环境基础:Docker 启动前后的网络差异

1. Docker 未启动时的默认网络情况

在未启动 Docker 前,宿主机执行ifconfig通常能看到:

  • ens33:宿主机的真实物理网卡

  • lo:本地回环网卡 (127.0.0.1)

  • virbr0:如果 CentOS 安装了虚拟化服务(libvirt),会生成一个以网桥连接的私网地址(如192.168.122.1),提供 NAT 访问外网的功能。如果不使用虚拟化,可以直接卸载:yum remove libvirt-libs.x86_64

2. Docker 启动后的网络情况

Docker 启动后,宿主机网络会产生一个名为docker0的虚拟网桥。

[root@zzyy ~]# ifconfig docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255

可以看到,它默认分配了172.17.0.1的网关 IP,它将在内核层连通所有容器和本地主机,放入同一个物理网络。


二、 常用基本命令与能干嘛?

  • 查看网络:docker network ls(默认会创建 bridge、host、none 三个网络)

  • 查看网络源数据:docker network inspect XXX网络名字

  • 删除网络:docker network rm XXX网络名字

  • 能干嘛:容器间的互联和通信、端口映射。最核心的是:容器 IP 变动时,可以通过服务名直接网络通信而不受影响。


三、 四大网络模式总体介绍与选型

可以通过--network参数指定不同模式:

模式核心特点典型场景启动命令参数
bridge独立网络空间,连接到docker0虚拟网桥普通项目,最常用,默认模式--network bridge
host直接使用宿主机网络,不虚拟自己的网卡对网络性能要求极高的程序、网络监控--network host
none基本没有网络,只有lo回环接口需要完全隔离网络的程序,不需要网络--network none
container共享另一个容器的网络空间(IP、端口范围)特殊协作场景,辅助容器--network container:NAME/ID

四、 网络模式深度拆解与真实环境排错

1. bridge 模式(默认,重点理解)

是什么:Docker 服务默认创建一个docker0网桥(虚拟交换机),将容器和宿主机放到同一个物理网络。

容器实例内默认网络IP生产规则与案例(IP 变动大坑):
启动两个 ubuntu 容器u1和u2,通过docker inspect查看 IP,发现分别为172.17.0.2和172.17.0.3。
如果关闭u2,新建u3,会发现u3的 IP 变成了172.17.0.3(复用了被释放的 IP)。

⚠️结论:docker 容器内部的 IP 是有可能会发生改变的!因此推荐使用服务名/容器名通信。

两两匹配验证(veth pair 机制):
在宿主机执行ip addr看到28: veth14fc73a@if27;进入容器执行ip addr看到27: eth0@if28。

🔍原理解析:@ifX表示对端接口编号。宿主机 28 ↔ 容器 27,这就证明这是一对 veth pair(虚拟网线)。

互通与抓包:

  • 容器 A 可以直接 ping 容器 B 的 IP,也能访问对方开启的服务。

  • 不能主动偷看对方流量:Linux 网络命名空间隔离,A 只能看到进出自己 eth0 的数据包。

  • 宿主机可以抓全部流量:在宿主机执行tcpdump -i docker0,就能抓到两个容器之间所有通信数据包(因为 docker0 网桥本身属于宿主机的网络命名空间)。

2. host 模式(避坑重点)

是什么:容器不会获得独立的 Network Namespace,而是和宿主机共用一个,直接使用宿主机的 IP 和端口,不需要额外 NAT 转换。
⚠️ 真实排错大坑:

# 错误示范:指定了 --network host 还指定 -p docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8 # 警告信息:WARNING: Published ports are discarded when using host network mode

原因:使用 host 模式时,-p设置的端口映射参数将不会起到任何作用,且端口号会以主机端口号为主,重复时则递增。
解决:使用 host 模式直接去掉-p参数,通过http://宿主机IP:端口直接访问。此时容器共享宿主机网络 IP,外部主机与容器可以直接通信。

3. none 模式

是什么:禁用网络功能。Docker 容器没有网卡、IP、路由等信息,只有一个lo(127.0.0.1) 标识。
使用场景:不需要网络的隔离环境。优点是隔离能力强,缺点是基本无法进行正常网络通信。

4. container 模式(特殊协作)

是什么:新创建的容器不会创建自己的网卡,而是和一个指定的容器共享 IP、端口范围等。两个容器除了网络方面,文件系统、进程列表等还是隔离的。
❌ 错误案例(端口冲突):共用网络时如果两个容器都映射相同的端口,会直接报错conflicting options: port publishing and the container type network mode.(相当于两个容器公用同一个 IP 和同一个端口,导致端口冲突)。
✅ 正确案例(Alpine 演示):

docker run -it --name alpine1 alpine /bin/sh docker run -it --network container:alpine1 --name alpine2 alpine /bin/sh

在 alpine1 和 alpine2 中分别执行ip addr,发现两者的eth0网卡 IP 完全一样,证明网络共用。
⚠️ 生命周期绑定坑:假如此时关闭 alpine1,再进入 alpine2 执行ip addr,发现eth0消失了,只剩下lo回环接口。证明 alpine2 的网络完全依赖 alpine1。


五、 端口映射与跨容器通信(解决外部访问与互联)

1. 端口映射(解决外部访问容器)

容器 IP(如172.17.0.2)是 Docker 内部网络,外部无法直接访问。通过端口映射-p解决。

  • 语法:-p 8080:80(宿主机端口:容器端口)。

  • 底层原理:用户访问服务器IP:8080-> 宿主机 8080 端口 -> Docker 转发/NAT -> 容器内部 80 端口 -> Nginx 服务。端口映射不是简单的“两个端口绑定”,而是 Docker 利用 Linux 网络转发和 NAT 等机制完成流量转发。

2. 跨容器通信(Docker DNS)
  • 推荐做法:自定义网络 + 容器名通信。

    docker network create mynet docker run -d --name backend --network mynet nginx docker run -d --name mysql --network mynet mysql

    在 backend 容器中直接连接mysql:3306。

  • 为什么不能写死 IP:容器 IP 可能发生变化(重启、重建后 IP 会变),容器名/服务名更加稳定,更容易维护。

  • 完整解析流程:Backend 发起请求 mysql:3306->Docker DNS 解析 mysql->解析到 172.18.0.3 容器 IP->目标端口。这也是 Docker Compose 中mysql:3306这种写法的基础。


六、 底层原理:Linux 网络能力的组合

Docker 网络本质上是把 Linux 提供的四大网络能力组合起来,为容器提供网络功能。

  1. Network Namespace(网络隔离的基础)
    让不同进程拥有独立的网络环境(独立的 IP、网卡设备、路由表、防火墙规则),互相看不到对方的网络配置。

  2. veth pair(虚拟网线)
    连接容器和宿主机。可以理解为一根虚拟网线,两端各有一个虚拟网卡。一端放在容器里(eth0),一端放在宿主机上(vethxxx)。容器eth0发出的数据包,通过 veth pair 这根“网线”,直接传到宿主机的网络线上。

  3. Linux Bridge(虚拟交换机)
    Docker 默认创建的docker0网桥,相当于 Linux 中的虚拟交换机。所有宿主机侧的 veth 全部接入同一个网桥。
    容器 A 和容器 B 通信路径:容器 A -> veth -> docker0 -> veth -> 容器 B。在同一网段下,二层可以直接互通,不需要经过宿主机路由转发。

  4. 路由与 NAT(解决容器访问互联网)
    容器的172.17.0.2属于 Docker 内部网络,外部网络无法直接识别和路由。通过NAT(网络地址转换),把容器的内部地址转换成宿主机可以对外通信的公网/局域网 IP 地址。

Docker 网络底层完整链路:

  • 容器之间通信:容器 A -> eth0 -> veth pair -> Linux Bridge -> veth pair -> eth0 -> 容器 B

  • 容器访问互联网:容器 -> veth -> docker0 -> 路由 -> NAT -> 宿主机网卡 -> 互联网


七、 核心知识总结(记住这四句话)

  1. 网络模式:决定容器使用什么网络环境(bridge/host/none/container)。

  2. 端口映射:解决外部如何访问容器(-p 宿主机端口:容器端口)。

  3. 跨容器通信:通过自定义网络 + Docker DNS,用容器名/服务名互相访问,规避 IP 变动带来的问题。

  4. 底层原理:Docker 利用 Linux 的 Network Namespace(网络隔离)、veth pair(虚拟网卡对)、Linux Bridge(虚拟交换机)、路由和 NAT(地址转换)等底层网络能力,组合构建了容器的网络世界。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询