2023-12-11
Docker
00

目录

Docker 网络详解(十一)
一、Docker 网络简介
1、是什么?
2、作用:
3、网络模式
4、docker网络命令
5、组件原理
(1)网络命名空间(network namespace)
(2)虚拟网络设备对(veth-pair)
(3)docker0 网桥
二、网络模式详细说明
1、Host 模式
2、None 模式
3、Bridge 模式
4、Container 模式
5、Custom 模式
三、自定义网络实战 - 网络联通
1、验证不同网络无法联通性
(1)创建容器 container1
(2)创建容器 container2
(3)两台容器之间互相 ping 测试
2、不同网络之间网络联通
(1)将容器 container1 和容器 container2 分别添加到对方所在的网络中
(2)再次检查两台容器之间网络联通性

Docker 网络详解(十一)

这篇文章介绍了Docker网络的五种类型:基础网络类型(bridge、host和none)和由基础网络类型派生的网络类型(container和custom)。网络命名空间是Linux内核提供的一种用于隔离不同容器间网络资源的重要功能。veth-pair则用于解决不同网络命名空间之间的通信,它是一种虚拟网络设备对,就像两块有网线连接的网卡。Docker使用虚拟网络设备对来实现不同容器间的通信。

Docker 网络详解(十一)

一、Docker 网络简介

1、是什么?

docker安装并启动服务后,会在宿主机中添加一个虚拟网卡。 在Docker服务启动前,使用 ifconfigip addr 查看网卡信息:

lo:本机回环网络网卡

使用 systemctl start docker启动Docker服务后,会多出一个 docker0 网卡。

2、作用:

  • 容器间的互联和通信以及端口映射
  • 容器IP变动时候可以通过服务名直接网络通信而不受到影响

Docker容器的网络隔离,是通过Linux内核特性 namespacecgroup 实现的。

3、网络模式

Docker 基础网络类型一共有三种(bridgehostnone),还有两种由基础网络类型派生的网络类型(containercustom)。本文详细讲解这五种网络类型。

查看 docker 网络:

bash
[root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE b3f041e614ec bridge bridge local d039b1004b4b host host local 8f512acdd2f6 none null local

网络模式说明:

网络模式配置说明
host--network=host容器不会创建自己的网卡,配置 IP 等,而是使用宿主机的 IP 和端口
none--network=none容器关闭网络功能,不进行任何网路设置
bridge--network=bridge为每个容器分配 IP 。并将容器连接到 docker0 虚拟网桥上,这种模式是默认模式
container--network=container
容器不会创建自己的网卡和IP,而是和一个指定的容器共享 IP 和端口
custom--network=new_bridge为每个容器分配 IP 。并将容器连接到自定义的虚拟网桥上

4、docker网络命令

操作命令描述
添加 Docker 网络docker network create xxx添加名为 xxx 的网络
删除 Docker 网络docker network rm xxx删除名为 xxx 的网络
查看网络元数据docker network inspect xxx查看名为 xxx 的网络信息
删除所有无效的网络docker network prune删除所有无效的网络

5、组件原理

(1)网络命名空间(network namespace)

Network Namespace 是 linux 内核提供的用于实现网络虚拟化的重要功能,是 Linux 内核用来隔离不同容器间的网络资源(每个 Docker 容器都拥有一个独立的网络命名空间),网络命名空间主要隔离的资源包括:

  • iptables规则表
  • 路由规则表
  • 网络设备列表

网络空间结构如下图所示,当系统中拥有 2 个网络命名空间:

https://image.myxuechao.com/docker/53.png

由于不同的网络命名空间之间是相互隔离的,所以不同的网络命名空间之间并不能直接通信。 就好比两台电脑,如果没有任何网线连接,它们之间是不能通信的。所以,Linux 内核提供了 虚拟网络设备对(veth) 这个功能,用于解决不同网络命名空间之间的通信。

(2)虚拟网络设备对(veth-pair)

虚拟网络设备对(veth-pair)用于解决不同网络命名空间之间的通信,可以将其看成是两块有网线连接的网卡。只要将其中一块网卡放置到网络命名空间A,另外一块网卡放置到网络命名空间B,那么两个不同的网络命名空间就能够通信,如下图所示:

https://image.myxuechao.com/docker/54.png

如上图所示,veth0 与 veth1 组成一个虚拟网络设备对。虚拟网络设备对就像管道一样,只要向其中一端发送数据,就可以从另外一端接收到数据。

Docker 就是使用 虚拟网络设备对 来实现不同容器之间的通信,其原理如下图:

https://image.myxuechao.com/docker/55.png

(3)docker0 网桥

Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。

Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。

查看 docker0 网桥:

bash
# 查看 bridge 所有信息 docker network inspect bridge # 查看 bridge com.docker.network.bridge.name": "docker0" 的名称 docker network inspect bridge | grep name #查看所有网络接口信息 ip a

查看 docker0 详细:

bash
[root@VM-8-17-centos ~]# docker network inspect bridge [ { "Name": "bridge", "Id": "b3f041e614ec48f5ffabb446a425f905ac689c7c8bd70fe4f4802eab5b54cfd2", "Created": "2023-10-24T00:00:01.550434451+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Containers": { "4cd859c037b8c925ba1ca6b99918537d30617155a7ba8706b0f4c8bd2b0d2525": { "Name": "stoic_euler", "EndpointID": "9752c42f4d838457a46360079c4285ad22c6b61d7ee979188d5a5554bea69e2e", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]

查看连接到 docker0 的虚拟网络设备对(veth-pair):

bash
[root@VM-8-17-centos ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.02429137dd65 no veth348e53d

注意:每启动一个容器,就会生成一个 veth-pair 。

如果没有 brctl 这个命令,可以通过以下命令进行安装:

bash
yum install -y bridge-utils

二、网络模式详细说明

1、Host 模式

在 host 模式下,容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP 和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。

结构如下图所示:

https://image.myxuechao.com/docker/56.png

查看该网络模式配置:

bash
[root@VM-8-17-centos ~]# docker network inspect host [ { "Name": "host", "Id": "d039b1004b4b2695c40287b25da6f6d8b4d91e7ae42b54920a7559826fa5263a", "Created": "2023-08-31T08:36:22.077011441+08:00", "Scope": "local", "Driver": "host", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [] }, "Internal": false, "Attachable": false, "Containers": {}, "Options": {}, "Labels": {} } ]

2、None 模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

结构如下图所示:

https://image.myxuechao.com/docker/57.png

查看该网络模式配置:

bash
[root@VM-8-17-centos ~]# docker network inspect none [ { "Name": "none", "Id": "8f512acdd2f6b6558cd327c2254ce027869dd3aecdf345e3cda1dc6ce39a283c", "Created": "2023-08-31T08:36:22.070115953+08:00", "Scope": "local", "Driver": "null", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [] }, "Internal": false, "Attachable": false, "Containers": {}, "Options": {}, "Labels": {} } ]

3、Bridge 模式

Bridge 模式是 docker 的默认网络模式,不写 --network 参数,就是 bridge 网桥模式。

当 Docker 进程启动时,会在主机上创建一个名为 docker0 的虚拟网桥,此主机上启动的Docker容器默认都会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

从 docker0子网中分配一个IP给容器使用,并设置 docker0 的IP地址为容器的默认网关。在主机上创建一对虚拟网卡 veth pair 设备,Docker 将 veth pair 设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以 vethxxx 这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过 brctl show 命令查看。

结构如下图所示:

https://image.myxuechao.com/docker/58.png

查看该网络模式配置:

bash
[root@VM-8-17-centos ~]# docker network inspect bridge [ { "Name": "bridge", "Id": "b3f041e614ec48f5ffabb446a425f905ac689c7c8bd70fe4f4802eab5b54cfd2", "Created": "2023-10-24T00:00:01.550434451+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Containers": { "4cd859c037b8c925ba1ca6b99918537d30617155a7ba8706b0f4c8bd2b0d2525": { "Name": "stoic_euler", "EndpointID": "9752c42f4d838457a46360079c4285ad22c6b61d7ee979188d5a5554bea69e2e", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]

4、Container 模式

Container 模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

结构如下图所示:

https://image.myxuechao.com/docker/59.png

在以上示例中,Docker 2 容器可以通过--network=container:Docker 1 参数,指定自己的网络和一个容器 Docker 1 共享 IP 和端口。

示例:

bash
docker run -it --name docker1 nginx:latest /bin/bash # 指定和 docker1 容器共享网络 docker run -it --name docker2 --network=container:docker1 nginx:latest /bin/bash

此时使用 ip addr查看两台容器的网络,会发现两台容器的eth0网卡内的IP等信息完全相同。

如果关掉了alpine1容器,因为alpine2的网络使用的alpine1共享网络,所以关掉alpin1后,alpine2eth0网卡也随之消失了。

5、Custom 模式

Custom 模式用于自定义 docker 网络。

结构如下图所示:

https://image.myxuechao.com/docker/60.png

如上图所示,新建自定义网桥 custom ,指定网络(192.168.10.0/24)和网关(192.168.10.1)。

bash
# 新建自定义网络 docker network create --driver bridge --subnet 192.168.10.0/24 --gateway 192.168.10.1 Custom # 查看自定义网络,查看定义网络 docker network ls NETWORK ID NAME DRIVER SCOPE 994c4bd64f70 bridge bridge local 9eeb43076ad2 host host local 24cd1b0769bd Custom bridge local ad2da4225045 none null local # 查看自定义网桥 IP 地址 [root@localhost ~]# ip addr 316: br-24cd1b0769bd: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:cb:b3:6c:a3 brd ff:ff:ff:ff:ff:ff inet 192.168.10.1/24 brd 192.168.10.255 scope global br-24cd1b0769bd valid_lft forever preferred_lft forever

三、自定义网络实战 - 网络联通

在没有使用 connect 命令的情况下,不同网络间的容器是无法进行网络连接的。

如下图所示:container1 和 container2,使用不同的网络,所以无法联通。

https://image.myxuechao.com/docker/61.png

1、验证不同网络无法联通性

(1)创建容器 container1

bash
# 创建容器 docker run -it --name container1 centosjava:latest /bin/bash # 查看容器 IP [root@0fa776c5eb80 local]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.3 netmask 255.255.0.0 broadcast 0.0.0.0 inet6 fe80::42:acff:fe11:3 prefixlen 64 scopeid 0x20<link> ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet) RX packets 23 bytes 1830 (1.7 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 22 bytes 1860 (1.8 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

(2)创建容器 container2

bash
# 创建容器 docker run -it --name container2 --network Custom centosjava:latest /bin/bash # 查看容器 IP [root@a42c80a672cd local]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.10.2 netmask 255.255.255.0 broadcast 0.0.0.0 inet6 fe80::42:c0ff:fea8:a02 prefixlen 64 scopeid 0x20<link> ether 02:42:c0:a8:0a:02 txqueuelen 0 (Ethernet) RX packets 47 bytes 2950 (2.8 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 526 bytes 50020 (48.8 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

(3)两台容器之间互相 ping 测试

可以直接 ping容器名,不需要ping IP地址 因为我们是自定义网络

bash
# 容器 container1 ping container2 ,不通 [root@41eea42d9980 /]# ping 192.168.10.2 PING 192.168.10.2 (192.168.10.2) 56(84) bytes of data. # 容器 container2 ping container1 ,不通 [root@7279af38152a /]# ping 172.17.0.8 PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.

2、不同网络之间网络联通

(1)将容器 container1 和容器 container2 分别添加到对方所在的网络中

bash
docker network connect Custom container1 docker network connect bridge container2

(2)再次检查两台容器之间网络联通性

bash
# 容器 container1 ping container2 ,通 [root@41eea42d9980 /]# ping 192.168.10.2 PING 192.168.10.2 (192.168.10.2) 56(84) bytes of data. 64 bytes from 192.168.10.2: icmp_seq=123 ttl=64 time=0.087 ms 64 bytes from 192.168.10.2: icmp_seq=124 ttl=64 time=0.085 ms # 容器 container2 ping container1 ,通 [root@7279af38152a /]# ping 172.17.0.3 PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data. 64 bytes from 172.17.0.3: icmp_seq=229 ttl=64 time=0.090 ms 64 bytes from 172.17.0.3: icmp_seq=230 ttl=64 time=0.077 ms

通过以上实战说明,docker 不同网络之间互联需要使用 connect 命令进行网络发布!!!

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:LiuXueChao

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!