- Dockers 是怎么管理网络的?
- 容器之间、容器与外部是如何通讯的?
- 如何自定义和管理 Docker 网络?
- 在微服务架构中,Docker 网络扮演什么样的角色?
一、 核心理论:容器网络模型 (CNM)
Docker 的网络功能是基于一个名为 容器网络模型 (Container Network Model, CNM) 的规范实现的。CNM 为不同的网络驱动提供了统一的抽象接口,其核心组件构成了 Docker 网络的基础。
- 沙箱 (Sandbox): 代表一个容器独立的网络栈,包括网络接口(veth pair)、端口、路由表和 DNS 配置。一个沙箱可以连接到多个网络。
- 端点 (Endpoint): 负责将沙箱连接到网络。它就像一个虚拟网卡,一端在沙箱内,另一端连接到指定的网络。一个端点只能属于一个网络和一个沙箱。
- 网络 (Network): 是可以相互通信的端点的集合。网络本身是可插拔的,通过不同的网络驱动(Driver)可以实现不同的网络拓扑和功能。
二、 Docker 网络驱动 (Network Drivers)
Docker 内置了多种网络驱动,以适应不同的应用场景。可以通过 docker network ls
命令查看当前主机上存在的 Docker 网络。
以下是几种核心网络驱动的详细解析:
1. Bridge (桥接) 网络
Bridge 是 Docker 安装后默认的网络驱动。当启动容器时未指定网络,它就会被连接到默认的 bridge
网络。
- 工作原理: Docker 在宿主机上创建一个名为
docker0
的虚拟网桥。所有连接到该网络的容器都会在宿主机上创建一对 veth pair(虚拟网络接口对),一端在容器内(通常是eth0
),另一端连接到docker0
网桥。Docker 会为容器分配私有 IP 地址,并通过配置 NAT 规则实现容器对外的访问。 - 特点:
- 提供主机内容器间的隔离和通信。
- 通过端口映射(Port Mapping)实现容器服务的对外暴露。
- 是 Docker 最常用、最经典的模式。
- 适用场景: 单机环境下运行多个需要相互通信的容器。
- 常用命令:
- 运行一个 Nginx 容器,并将容器的 80 端口映射到宿主机的 8080 端口:
docker run -d --name web-server -p 8080:80 nginx
- 运行一个 Nginx 容器,并将容器的 80 端口映射到宿主机的 8080 端口:
2. Host (主机) 网络
Host 网络模式下,容器将直接共享宿主机的网络命名空间。
- 工作原理: 容器不再拥有独立的网络栈,而是直接使用宿主机的网络接口和 IP 地址。
- 特点:
- 网络性能最高,因为它绕过了虚拟化网络层,性能几乎等同于宿主机上的原生进程。
- 容器端口直接暴露在宿主机上,无需端口映射,但也容易引发端口冲突。
- 牺牲了容器的网络隔离性,安全性较低。
- 适用场景: 对网络性能有极致要求,且可以接受牺牲网络隔离性的特定场景,如网络监控或需要处理大量数据包的应用。
- 常用命令:
docker run -d --net=host nginx
3. None (无) 网络
None 网络模式下,容器拥有独立的网络命名空间,但 Docker 不会为其进行任何网络配置。
- 工作原理: 容器被创建后,其网络栈中只有一个
lo
(loopback) 接口,没有任何外部网络连接。 - 特点:
- 容器完全与外界隔离,提供了最高的网络安全性。
- 适用场景:
- 执行批处理任务或计算任务,完全不需要网络的容器。
- 需要使用自定义网络工具(如
pipework
)进行高度定制化网络配置的场景。
- 常用命令:
docker run --rm --net=none alpine ip addr
4. Overlay (覆盖) 网络
Overlay 网络是一种分布式网络,用于连接运行在不同宿主机上的 Docker 容器,是实现 Docker Swarm 集群中跨主机容器通信的核心。
- 工作原理: Overlay 网络通过 VXLAN 等隧道技术,在多个 Docker 宿主机之间创建一个虚拟的二层网络。它使得不同主机上的容器感觉就像在同一个局域网中一样,可以直接通过 IP 地址通信。它通常需要一个键值存储服务(如 Swarm 内置的 Raft store)来维护网络状态。
- 特点:
- 原生支持跨主机容器通信。
- 为 Swarm 服务提供了内置的服务发现和负载均衡功能。
- 配置相对复杂,但功能强大。
- 适用场景: Docker Swarm 集群环境下的多机、多容器应用部署。
- 常用命令:
- (在 Swarm manager 节点上)创建一个 Overlay 网络:
docker network create -d overlay my-swarm-network
后日记:k8s与Docker Swarm中的跨Node的通讯协议都是基于此来实现的 Kubernetes和Docker Swarm都需要Overlay网络来实现跨主机通信。区别在于,Docker Swarm将其作为内置功能直接提供,而Kubernetes通过CNI插件生态系统来提供,用户选择的CNI插件(如Flannel)在底层实现了Overlay网络。
后日记:k8s中另外两种网络驱动
macvlan
和ipvlan
5. Macvlan 网络
- 工作原理: 允许你为容器分配一个 MAC 地址,使其在网络上显示为一台独立的物理设备。容器的流量通过指定的物理网卡(例如
eth0
)直接路由,而不是通过docker0
网桥进行 NAT 转换。 - 特点:
- 性能极高,接近物理机。
- 容器直接暴露在外部网络,可以被网络中的其他设备直接访问,无需端口映射。
- 非常适合那些需要与物理网络设备(如路由器、防火墙)直接交互的传统应用。
- 注意: 默认情况下,使用
macvlan
的容器无法与宿主机直接通信。
6. Ipvlan 网络
- 工作原理: 与
macvlan
类似,但工作在 L3(IP 层)。同一网络下的所有容器共享宿主机的 MAC 地址,但拥有各自独立的 IP 地址。 - 特点:
- 同样具有很高的性能。
- 相比
macvlan
,ipvlan
对物理网络设备更友好,因为不会产生大量的 MAC 地址(避免了交换机的 MAC 地址表耗尽问题)。
三、 自定义网络的应用
虽然 Docker 提供了默认的 bridge
网络,但在生产环境中,强烈推荐为应用创建自定义的 bridge
网络。
-
核心优势:
- 自动服务发现: 自定义网络提供了内置的 DNS 服务。在同一自定义网络中的容器,可以直接通过 容器名 作为主机名进行通信。
- 更好的隔离性: 自定义网络提供了更好的网络隔离。默认情况下,不同自定义网络中的容器无法通信,保证了应用的安全性。而默认的
bridge
网络中的所有容器都可以互相访问。 - 动态连接管理: 可以随时将一个正在运行的容器连接到或断开一个自定义网络,而无需重启容器。
-
常用命令:
-
创建一个自定义 bridge 网络:
docker network create my-app-net
-
运行容器时指定网络:
docker run -d --name=database --net=my-app-net postgres
docker run -d --name=api --net=my-app-net my-api-image
查看网络的详细信息,包括连接到该网络的容器:
docker network inspect my-app-net
- 将一个正在运行的容器连接到网络:
docker network connect my-app-net some-running-container
四、容器互连
场景:不同桥接网卡网段容器有连接需求
docker network create my-net01
docker network create --subnet=10.10.0.0/24 my-net02
# 在 my-net01 启动容器
docker run -d --name web --network my-net01 nginx
# 在 my-net02 启动容器
docker run -d --name db --network my-net02 nginx
# 测试 web 到 db 的连通性
docker exec web ping db
原因:不同桥接网段IP为不同子网段,默认隔离
解决办法:容器加入多个网络
# 将 db 容器加入 web 所在的网络
docker network connect my-net01 db
# 再次测试(成功)
docker exec web ping db
# 使用 inspect 查看 db 容器网络 出现了多网卡地址