Datawhale-Docker学习笔记-0004-Docker网络
1. Docker网络
Docker在容器内部运行着大量需要依赖不同网络的应用,这也就意味着Docker需要非常强大的网络功能。当然,Docker对于容器之间、容器与外部网络的连接均有相应的解决方案。
我们可以从顶层设计的角度学习Docker的网络架构。
Docker网络架构主要由3个部分构成:CNM,Libnetwork和驱动。
CNM是设计标准,其中规定了Docker网络架构的基本组成要素。Libnetwork是CNM的具体实现,通过GO语言实现了CNM中所列举的核心组件。而驱动则是通过实现特定网络拓扑的方式来扩展该模型的能力。
1.1 CNM
Docker使用的设计规范是CNM,在CNM中规定了Docker网络的基础组成要素。我们可以在docker/libnetwork中查看完整的内容。在CNM中定义了3个基本的要素:
- 沙盒:一个独立的网络栈,其中包括以太网接口、端口、路由表以及DNS配置。
- 终端:虚拟的网络接口。主要负责将沙盒连接到网络中。
- 网络:网桥的软件实现,就是交换机。可以看成需要交互的终端的集合,并且终端之间相互独立。
我们需要特殊理解终端的含义。在容器内部,会有一个沙盒,而终端则是将沙盒和网络连接起来。但是就像路由器一样,一个网络接口只能连接一个网络。所以如果容器想要连接进多个网络的话,则需要有多个终端才能完成。
1.2 Libnetwork
Libnetwork就是CNM的具体实现。我们需要了解一下Libnetwork中实现的具体功能。除了CNM中定义的3个组件以外,Libnetwork中还实现了本地服务发现,基于Ingress的容器负载均衡,以及网络控制层和管理层的功能。
1.3 驱动
如果说Libnetwork中实现了控制层和管理层的工作,那么驱动就负责实现数据层的工作。每个驱动都负责这些驱动上的网络资源的创建和管理。
2. 单机桥接网络
我们想要说明什么是单机桥接网络的话,首先要说明什么是桥接网络。在Docker中,支持4种网络模式。
网络模式 | 简介 |
---|---|
Bridge | 桥接模式。为每一个容器分配、设置IP。并将容器连接到一个docker0的虚拟网桥上,默认是这种方式。 |
Host | 容器使用的是宿主机的IP和端口 |
None | 容器有独立的网络命名空间,但没有进行任何配置 |
Container | 新创建的容器不会创建自己的网卡和配置自己的IP,而是和指定容器共享IP和端口范围等 |
而单机桥接网络,从名字种就可以看出它的功能。只能在单个Docker主机上运行,只能与所在的Docker主机上的容器进行连接。且使用的是桥接网络。需要注意的是,在Linux上使用的是内置的桥接驱动,在Windows上则使用的是NAT驱动。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nl44tbFB-1618825088578)(E:\Docker\network ls.png)]
我们可以使用docker network ls指令来查看所有网络。每一个Docker主机上都会有一个默认的桥接网络,在Linux上命名为bridge,在windows上命名为nat。除非我们在运行容器的时候指定–network参数,否则都会默认的连接到该网络。
C:\Users\81991>docker network inspect bridge
[
{
"Name": "bridge",
"Id": "484bfd08ee5b4b7d6220e6604b6a37bc0f05a1f3b1ab74df8869143dd4a15381",
"Created": "2021-04-19T06:51:46.4591893Z",
"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": {}
}
]
通过inspect指令,我们可以看到一些有意思的东西。比如,我们可以看到网桥的名称为docker0。当Docker
进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上,附加在其上的任何网卡之间都能自动转发数据包。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker 将 veth pair 设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到 docker0 网桥中。
还可以通过brctl show指令来查看桥的内容。当然,前提是你需要安装brctl的二进制包。
3. Host、None、container模式
除了Bridge模式以外,另外三种模式都需要在运行容器的时候指定模式。也就是run指令的’–network’选项。
采用 host 网络模式的 Docker Container,可以直接使用宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。但是这样也有会很多缺点,容器的网络缺少了隔离性。
none 网络模式是指禁用网络功能,只有 lo 接口 local 的简写,代表 127.0.0.1,即 localhost 本地环回接口。在创建容器时通过参数 --net none或者 --network none指定。none 网络模式即不为 Docker Container 创建任何的网络环境,容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。可以说 none 模式为 Docke Container 做了极少的网络设定,但是俗话说得好“少即是多”,在没有网络配置的情况下,作为 Docker 开发者,才能在这基础做其他无限多可能的网络定制开发。这也恰巧体现了 Docker 设计理念的开放。
Container 网络模式是 Docker 中一种较为特别的网络的模式。在创建容器时通过参数 --net container:已运行的容器名称|ID或者
–network container:已运行的容器名称|ID 指定。
4. 端口映射
如果想要在外部访问docker的应用,我们可以进行端口的映射。
- 使用 -P 选项可以随机映射一个主机端口到容器内部的网络端口上
- 使用 -p 选项可以指定要映射的端口。可以是
hostport:containerport
, 也可以是ip:hostport:containerport
,甚至可以是ip:containerport
。
我们可以通过docker port
指令来查看端口的配置。