一、Bridge网络
bridge网络表现形式就是docker0这个网络接口。容器默认都是通过docker0这个接口进行通信。也可以通过docker0去和本机的以太网接口连接,这样容器内部才能访问互联网。
查看docker0网络,在默认环境中,一个名为docker0的linux bridge自动被创建好了,其上有一个 docker0 内部接口,IP地址为172.17.0.1/16。通过命令:ip a
查看docker网络
docker network ls
查看bridge网络详情。主要关注Containers节点信息。
docker network inspect bridge
输出如下:
[
{
"Name": "bridge",
"Id": "8f2bb7721e07845f809dab6cfeefccc5145cbb99953bbe090d5c349af5bf5fa1",
"Created": "2024-01-22T22:29:27.110338803+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,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"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": {}
}
]
我们看到Containers这个节点下,没有值,也就是没有任何容器加入这个网络环境
1.1、docker0详解
1、拉取镜像
docker pull nginx:1.19.3-alpine
2、运行镜像
docker run -itd --name nginx1 nginx:1.19.3-alpine
3、观察bridge网络
docker network inspect bridge
可以看到nginx的网络ip地址是172.17.9.2
。这个是因为docker0的网络地址范围是172.17.0.1
~172.17.255.255
4、查看宿主机上的网卡
// 用于显示或操作系统的网络接口信息
ip a
发现多出一块网卡veth0ce8f41@if9
veth
(Virtual Ethernet)是Linux网络命名空间中的一种虚拟网络设备类型。它总是成对出现,就像一个虚拟的以太网线缆,一端插在一个网络命名空间,另一端插在另一个网络命名空间或者主机的全局网络命名空间。
veth
对在容器技术(如Docker)中实现网络隔离和通信非常有用。例如,当你在Docker中启动一个新的容器时,Docker会创建一对veth
接口。一个接口在新的容器的网络命名空间中,另一个接口在主机的网络命名空间中。这样,容器就可以通过这对veth
接口与主机和其他容器通信。
Docker创建一个容器的时候,会执行如下操作:
- 创建一对虚拟接口/网卡,也就是veth pair,分别放到本地主机和新容器中;
- 本地主机一端桥接到默认docker0或指定网桥上,并具有一个唯一的名字,如veth0ce8f41@if9`;
- 容器一端放到新容器中,并修改名字作为eth0,这个网卡/接口只在容器的名字空间可见;
- 从网桥可用地址段中(也就是与该bridge对应的network)获取一个空闲地址分配给容器的eth0,并配置默认路由到桥接网卡veth0ce8f41@if9:。
完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。 如果不指定–network,创建的容器默认都会挂到 docker0 上,使用本地主机上 docker0 接口的 IP 作为 所有容器的默认网关
第一种方式:
docker exec -it nginx1 sh
ip a
第二种方式:
docker exec -it nginx1 ip a
安装brctl
brctl
是一个用于设置和管理Linux桥接设备的命令行工具。在大多数Linux发行版中,brctl
包含在bridge-utils
软件包中。
yum install -y bridge-utils
运行命令
brctl show
1.2、多容器之间通信
1、再安装一个nginx
docker run -itd --name nginx2 nginx:1.19.3-alpine
2、查看bridge网络
docker network inspect bridge
3、显示结果
"Containers": {
"3c178352ba547b43d84d1027bd268cf037488a7351cf5bb18c09b8a326a7986a": {
"Name": "nginx1",
"EndpointID": "21c8a36dcf1b22414098f112af7ff5a896180fd60d88f918cf220e2de4cb1aeb",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"bc60737cd65607de4224337766c01a7e3e0177e401ab1170e76cfe00a4b083c2": {
"Name": "nginx2",
"EndpointID": "b10d02f3435c51053c7ddb4b1c915b2bef9e90a79caf9b0819ae2316a7ef9a4a",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
4、运行brctl show
brctl show
命令用于显示系统中所有的网络桥接器及其相关信息。
问题点:
每次重启docker的时候,容器的ip地址会变,谁先启动,谁获取前面的ip地址。开发人员不能在代码中写死数据库的IP地址。举个例子:
在企业开发环境中,有个msql服务容器mysql5
,还有个web服务容器tomcat8
,tomcat8肯定要连接mysql5,需要知道对方的真实ip地址。这时候我们就需要使用容器名来ping,而不是ip地址
二、新建Bridge网络
docker network create -d bridge test-bridge
这条命令是用来在Docker中创建一个新的网络桥接器的。
docker network create
是用来创建新的网络的命令,-d bridge
指定了网络的驱动类型为桥接,test-bridge
是你为新创建的网络桥接器指定的名称。
创建完成后,你可以使用docker network ls
命令来查看所有的网络,包括你刚刚创建的test-bridge
网络。
你也可以在运行新的容器时,使用--network=test-bridge
参数来指定容器使用这个新创建的网络。
当然如果你就要创建bridge。可以不带-d的参数。
image-20240122233909390
2.1、brctl show查看
image-20240122234038290
说明这个网卡还没有绑定容器
2.2、启动nginx3绑定test-bridge网卡
docker run -itd --name nginx3 --network test-bridge nginx:1.19.3-alpine
启动一个nginx的容器nginx3,并通过参数network connect来连接test-bridge网络。
image-20240122234323512
bridge绑定了新的网卡
2.3、把一个运行中容器连接到test-bridge网络
docker network connect test-bridge nginx2
2.4、创建自定义网络的好处
当你在Docker中创建一个自定义网络时,Docker会为该网络启用一个内置的DNS服务器。这个DNS服务器会自动为加入该网络的每个容器提供DNS解析服务。
这意味着,当你的容器加入到这个自定义网络时,它们可以使用其他容器的名称来进行网络通信,而不需要知道其他容器的IP地址。这是因为Docker的内置DNS服务器会自动将容器的名称解析为其内部IP地址。
例如,假设你有两个在同一个自定义网络中的容器,名为container1
和container2
。在container1
中,你可以直接使用ping container2
来pingcontainer2
,而不需要知道container2
的IP地址。
这个特性使得在Docker中管理和连接容器变得更加简单,因为你不需要手动管理和配置IP地址。
2.5、docker0默认不能互访的原因
Docker的默认桥接网络(通常被称为docker0
)是在Docker首次安装时创建的。这个默认网络的设计目标是为了让Docker能够“开箱即用”,而不需要用户进行任何额外的网络配置。
然而,docker0
网络并没有启用Docker的内置DNS服务。这意味着在docker0
网络中的容器不能直接通过容器名进行通信,必须使用容器的IP地址。这是一个已知的限制,是为了保持向后兼容性和简单性。
如果你需要使用容器名进行通信,你可以创建一个自定义的桥接网络。在自定义网络中,Docker的内置DNS服务是默认启用的。你可以使用docker network create
命令来创建一个自定义网络,然后在运行容器时使用--network
参数来指定容器加入这个网络。
三、none、host网络
3.1、none网络
环境准备,先stop和rm掉全部之前开启的容器。并且把前面创建的test-bridge网络也删除。当然,更简单的办法是使用快照方式。将虚拟机恢复到docker初始化安装时。或者手动删除容器与网络
docker rm -f $(docker ps -aq)
docker network rm test-bridge
docker network ls
启动一个ngnix的容器nginx1,并且连接到none网络。然后执行docker network inspect none,看看容器信息
docker run -itd --name nginx1 --network none nginx:1.19.3-alpine
docker network inspect none
image-20240123232817227
注意,容器使用none模式,是没有物理地址和IP地址。我们可以进入到nginx1容器里,执行ip a
命令看 看。只有一个lo接口,没有其他网络接口,没有IP。也就是说,使用none模式,这个容器是不能被其他 容器访问。这种使用场景很少,只有项目安全性很高的功能才能使用到。例如:密码加密算法容器。
知识点:
lo
接口,全称为 “loopback” 接口,是一个特殊的网络接口,用于网络软件的测试和本地通信。
当你向 lo
接口发送数据时,数据不会被发送到网络上,而是直接返回到发送者。这就像你在一个封闭的房间里大声说话,声音会反射回来,你可以听到自己的声音。
lo
接口通常有一个特殊的 IP 地址 127.0.0.1
(也被称为 “localhost”)。当你向这个地址发送数据时,数据会被发送到 lo
接口,然后直接返回到发送者。
lo
接口在网络软件的开发和测试中非常有用。例如,你可以在同一台机器上运行客户端和服务器程序,然后使用 lo
接口进行通信,以测试它们的功能。
docker exec -it nginx1 sh
image-20240123233007075
3.2、host网络
启动一个nginx的nginx2容器,连接到host网络。然后docker network inspect host, 看看容器信息
docker run -itd --name nginx2 --network host nginx:1.19.3-alpine
docker network inspect host
image-20240123233320208
这里来看,也不显示IP地址。那么是不是和none一样,肯定不是,不然也不会设计none和host网络进 行区分。下面我们进入nginx2容器,执行ip a
看看效果。我们在容器里执行ip a
,发现打印内容和在 linux本机外执行ip a
是一样的。
docker exec -it nginx2 sh
image-20240123233439168
这说明什么呢?容器使用了host模式,说明容器和外层linux主机共享一套网络接口。VMware公司的虚拟机管理软件,其中网络设置,也有host这个模式,作用也是一样,虚拟机里面使用网络和你自己外层机器是一模一样的。这种容器和本机使用共享一套网络接口,缺点还是很明显的,例如我们知道web服务器一般端口是80,共享了一套网络接口,那么你这台机器上只能启动一个nginx端口为80的服务器了。否则,出现端口被占用的情况。
四、总结
Docker 提供了多种网络模式,以满足不同的应用场景:
- 桥接网络(bridge):这是 Docker 的默认网络模式。在这种模式下,Docker 为每个容器分配一个私有的网络空间,并为每个容器创建一个虚拟网络接口,然后将这个接口连接到一个虚拟桥接器上。Docker 还会在宿主机上创建一个
docker0
网桥,并将所有容器的虚拟网络接口连接到这个网桥上,从而实现容器之间的通信。 - 主机网络(host):在这种模式下,容器直接共享宿主机的网络,没有自己的网络空间。这种模式的优点是网络性能高,但缺点是容器的网络隔离性差。
- 无网络(none):在这种模式下,容器没有自己的网络空间,也不能访问宿主机的网络。这种模式通常用于需要高度隔离的场景。
- 用户定义网络(user-defined network):Docker 允许用户创建自定义的网络,并将容器连接到这些网络上。用户定义网络可以是桥接网络、覆盖网络(overlay)或者 MACVLAN 网络。覆盖网络用于跨主机的容器通信,MACVLAN 网络用于将容器直接连接到物理网络。
如果刚接触docker对这块网络没有什么概念的话,安装镜像就会遇到一系列问题。比如我们在使用docker安装es与kibana的时候,会遇到kibana连不上es的问题,直到你了解docker设计的网络的原理,才能正确安装。总之,多多练习。