概述
容器网络是指容器之间或非 Docker 工作负载之间连接和通信的能力。容器默认启用网络,并且可以建立传出连接。容器不知道它所连接的网络类型,容器只能看到带有 IP 地址、网关、路由表、DNS 服务和其他网络详细信息的网络接口。也就是说,除非容器使用none网络驱动程序。
网络类型
driver | 描述 |
bridge | 默认网络驱动程序。当您的应用程序在需要与同一主机上的其他容器通信的容器中运行时,通常会使用桥接网络。 |
host | 移除容器和 Docker 主机之间的网络隔离,直接使用主机的网络。 |
none | 将容器与主机和其他容器完全隔离。 |
overlay | Overlay 将多个 Docker 守护进程连接在一起,并使 Swarm 服务和容器能够跨节点通信。此策略消除了进行操作系统级路由的需要。 |
ipvlan | IPvlan 网络提供对 IPv4 和 IPv6 寻址的完全控制。VLAN 驱动程序建立在其之上,使运营商能够完全控制第 2 层 VLAN 标记,甚至为对底层网络集成感兴趣的用户提供 IPvlan L3 路由。 |
macvlan | Macvlan 网络允许您为容器分配 MAC 地址,使其在网络上显示为物理设备。Docker 守护进程通过 MAC 地址将流量路由到容器。macvlan 在处理希望直接连接到物理网络而不是通过 Docker 主机的网络堆栈路由的遗留应用程序时,使用驱动程序有时是最佳选择。 |
具体说说
bridge
就 Docker 而言,bridge 网络使用软件桥接,让连接到同一 bridge 网络的容器进行通信,同时提供与未连接到该bridge网络的容器的隔离。Docker bridge 驱动程序会自动在主机中安装规则,以便不同桥接网络上的容器无法直接相互通信。
bridge 使用 Linux 网桥和 iptables 提供容器互联,Docker 在每台主机上创建一个名叫 docker0的网桥,通过 veth pair(一头连到 docker0网桥,一头 设置为容器的eth0) 来连接该主机的每一个 EndPoint.其流程如下:
在shell 执行 docker network ls 可以看到我们的网络(默认和我们创建的)
[root@linjian ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
770ec16c3825 app-tier bridge local
cec3414e2d8c bridge bridge local
9c36c1f845a1 home_default bridge local
1ca06cf881dc host host local
b13d98abb5f8 none null local
可以使用--network bridge 选项可以指定启用bridge模式,bridge 是默认的网络模式,所以一般不指定也可以
docker run -itd --name mycontainer --network bridge xxx
我们可以先拉起两个alpine 两个容器
docker run -dit --name alpine1 alpine ash
docker run -dit --name alpine2 alpine ash
通过docker ps | grep alpine 可以看到已经拉起了
[root@linjian ~]# docker ps | grep alpine
217da339a460 alpine "ash" 32 seconds ago Up 31 seconds alpine2
0d2e33ce99ea alpine "ash" 33 seconds ago Up 32 seconds
检查bridge网络以查看有哪些容器连接到它。
进到容器可以看到,可以成功ping到对方的服务
Host
容器使用host网络模式,则该容器的网络堆栈不会与 Docker 主机隔离(容器共享主机的网络命名空间),并且容器不会分配自己的 IP 地址。例如,如果您运行绑定到端口 80 的容器并且使用host 网络,则该容器的应用程序可在主机 IP 地址的端口 80 上使用。
主机模式网络对于以下用例非常有用:
- 优化性能
- 在容器需要处理大范围端口的情况下
这是因为它不需要网络地址转换 (NAT),并且不会为每个端口创建“用户层代理”。
主机网络驱动程序仅适用于 Linux 主机,Docker Desktop for Mac、Docker Desktop for Windows 或 Docker EE for Windows Server 不支持。
拉起一个aline,并用--network 指定host。
[root@linjian ~]# docker run -itd -p 9561:9561 --network host --name alpine_host alpine
WARNING: Published ports are discarded when using host network mode
5b0e2d67fdb4d34a291f2357b4fde79522e568cc81b67a49f8c131a9d056a825
这里注意一个WARNING: 使用host网络模式,容器没有自己的 IP 地址 host, 端口映射不会生效,并且-p、--publish、-P和--publish-all选项将被忽略,而是产生警告。
进到容器 ping www.baidu.com,发现可以访问的了百度,已经和宿主机共享网络了
[root@linjian ~]# docker attach alpine_host
/ # ping www.baidu.com
PING www.baidu.com (180.101.50.242): 56 data bytes
64 bytes from 180.101.50.242: seq=0 ttl=50 time=10.128 ms
64 bytes from 180.101.50.242: seq=1 ttl=50 time=10.086 ms
64 bytes from 180.101.50.242: seq=2 ttl=50 time=10.063 ms
ç64 bytes from 180.101.50.242: seq=3 ttl=50 time=10.077 ms
overlay
如果是多台机器之间的容器需要访问,就可以使用overlay 网络模式。
在使用 overlay 前我们需要在一台机器(master)执行 docker swarm init 创建 swarm manager.
创建swarm manager
docker swarm init
[root@linjian ~]# docker network create --driver overlay overlayNet
docker swarm join --token SWMTKN-1-xxxxxxx xxx.xx.xxx.xxx:xxx
[root@linjian ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
feb2f19dd8b9 alpine-test bridge local
770ec16c3825 app-tier bridge local
cec3414e2d8c bridge bridge local
b438a2ffeac8 docker_gwbridge bridge local
9c36c1f845a1 home_default bridge local
1ca06cf881dc host host local
u3zrqntexbvi ingress overlay swarm
egfaukedlf8g overlayNet overlay swarm
创建网络
一台机器安装
docker run -itd --network overlayNet --name overlay-alpine01 alpine:latest ash
在另外一台机器安装
docker run -itd --name overlay-alpine02 --network overlayNet alpine:latest ash
测试
docker exec -it overlay-alpine02 ping overlay-alpine01
none
如果你想完全隔离容器的网络堆栈,可以--network none在启动容器时使用该标志。在容器内,仅创建环回设备。
host 网络模型的时候我们可以看到容器的网络配置
我们创建一个网络类型 None的看看,只有一个lo回环网络
[root@linjian ~]# docker run --rm --network none --name no-net-alpine alpine:latest ip addr show
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
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
Macvlan
一些应用服务希望直接连接到物理网络,比如说核心应用程序或监控网络流量的应用程序。在这种情况下,您可以使用macvlan网络驱动程序为每个容器的虚拟网络接口分配一个MAC地址,使其看起来像是直接连接到物理网络的物理网络接口。需要在Docker主机上指定一个物理接口用于Macvlan,以及网络的子网和网关,甚至可以使用不同的物理网络接口隔离Macvlan网络。
创建一个macvlan 名为 的网络 my-macvlan-net
docker network create -d macvlan --subnet=<subnet> --gateway=<gateway> -o parent <physical_interface> <network_name>
subnet :一个可用于Macvlan网络的子网地址;
gateway:Macvlan网络的网关地址;
physical_interface:宿主机上用于连接到物理网络的接口名称; (这个可以通过ip addr show 查看)
network_name:Macvlan网络的名称。
[root@linjian ~]# docker network create -d macvlan \
> --subnet=172.16.86.0/24 \
> --gateway=172.16.86.1 \
> -o parent=eth0 \
> my-macvlan-net
78595591dbc064da42574e27fbd1ed9a2ebf5b4312fe391d645adf801eeb8099
通过docker network ls和docker network inspect my-macvlan-net 命令来验证网络是否存在my-macvlan-net 并且是一个macvlan网络
[root@linjian ~]# docker network ls | grep my-macvlan-net
78595591dbc0 my-macvlan-net macvlan local
[root@linjian ~]# docker network inspect my-macvlan-net
[
{
"Name": "my-macvlan-net",
"Id": "78595591dbc064da42574e27fbd1ed9a2ebf5b4312fe391d645adf801eeb8099",
"Created": "2023-12-28T17:33:18.259298162+08:00",
"Scope": "local",
"Driver": "macvlan",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.16.86.0/24",
"Gateway": "172.16.86.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"parent": "eth0"
},
"Labels": {}
}
]
查看容器信息,docker inspect my-macvlan-alpine
启动一个容器并将其连接到my-macvlan-net网络, 查看网络信息
[root@linjian ~]# docker attach my-macvlan-alpine
/ # ip addr show eth0
30: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:10:56:02 brd ff:ff:ff:ff:ff:ff
inet 172.16.86.2/24 brd 172.16.86.255 scope global eth0
valid_lft forever preferred_lft forever
IPvlan
IPvlan 驱动程序让用户可以完全控制 IPv4 和 IPv6 寻址。Linux实现非常轻量级,因为它们不是使用传统的Linux网桥进行隔离,而是与Linux以太网接口或子接口相关联,以强制分离网络和物理网络的连接。
IPvlan 与 Macvlan 类似,但不为容器分配唯一的 MAC 地址,而是通过虚拟的MAC地址来访问网络。在使用IPvlan需要注意 Linux 内核 v4.2+(uname -r 查看)
ipvlan 有两种不同的模式:L2 和 L3。
L2
和 macvlan bridge 模式工作原理类似,父接口作为交换机来转发子接口的数据。同一个网络的子接口可以通过父接口来转发数据,而如果想发送到其他网络,报文则会通过父接口的路由转发出去。
L3
IPvlan 将要求将路由分发到每个端点。驱动程序仅构建 IPvlan L3 模式端口并将容器附加到接口。整个集群的路由分布超出了这个单一主机范围驱动程序的初始实现。在 L3 模式下,Docker 主机非常类似于在容器中启动新网络的路由器。
创建ipvlan网络
docker network create -d ipvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o ipvlan_mode=l2 \
-o parent=eth0 db_net
- -d ipvlan 指定网络驱动程序为Ipvlan
- --subnet 指定网络子网
- --gateway 指定网络网关
- -o parent 指定网络接口
- -o ipvlan_mode 设置 IPvlan 工作模式。可以是以下之一:l2, l3,l3s (默认bridgel2)
- ipvlan-network 是网络的名称
- ipvlan_flag 设置 IPvlan 模式标志。可以是以下之一:bridge, private,vepa(默认bridge)
拉起alpine容器并使用ipvlan网络
docker run --net=db_net -it --rm alpine /bin/sh