一、Docker为什么需要网络管理
容器的网络默认与宿主机及其他容器都是相互隔离, 但同时我们也要考虑下面的一些问题, 比如:
- 多个容器之间是如何通信的
- 容器和宿主机是如何通信的
- 容器和外界主机是如何通信的
- 容器中要运行一些网络应用(如 nginx、 web 应用、数据库等),如果要让外部也可以访问这些容器内运行的网络应用应该如何实现
- 容器不想让它的网络与宿主机、与其他容器隔离应该如何实现
- 容器根本不需要网络的时候应该如何实现
- 容器需要更高的定制化网络(如定制特殊的集群网络、定制容器间的局域网)应该如何实现
- …
上述的这些问题都需要我们对容器的网络进行合理的管理才能解决,这就体现出了容器网络管理的重要性。
二、Docker网络架构简介
Docker 容器网络
是为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作系统的网络环境中独立出来,形成容器自有的网络设备、 IP 协议栈、端口套接字、 IP路由表、防火墙等等与网络相关的模块。
Docker 为实现容器网络,主要采用的架构由三部分组成:CNM
、 Libnetwork
和驱动
。
CNM
Docker 网络架构采用的设计规范是 CNM(Container Network Model)。 CNM 中规定了 Docker 网络的基础组成要素: Sandbox
、 Endpoint
、 Network
。
-
Sandbox
:提供了容器的虚拟网络栈,也即端口、套接字、 IP 路由表、防火墙、DNS 配置等内容。主要用于隔离容器网络与宿主机网络,形成了完全独立的容器网络环境。 -
Network
: Docker 内部的虚拟子网,使得网络内的参与者能够进行通讯。 -
Endpoint
:就是虚拟网络的接口,就像普通网络接口一样, Endpoint 的主要职责是负责创建连接。 Endpoint 类似于常见的网络适配器,那也就意味着一个 Endpoint 只能接入某一个网络, 当容器需要接入到多个网络,就需要多个 Endpoint。
如上图所示,容器 B 有两个 Endpoint 并且分别接入 Networkd A 和 Network B。那么容器 A 和容器 B 之间是可以实现通信的,因为都接入了 NetworkA。但是容器 A 和容器 C 不可以通过容器 B 的两个 Endpoint 通信。
Libnetwork
Libnetwork
是 CNM 的一个标准实现。 Libnetwork 是开源库,采用 Go 语言编写(跨平台的),也是 Docker 所使用的库, Docker 网络架构的核心代码都在这个库中。Libnetwork 实现了 CNM 中定义的全部三个组件,此外它还实现了本地服务发现、基于 Ingress 的容器负载均衡,以及网络控制层和管理层等功能。
驱动
驱动
主要负责实现数据层相关内容,例如网络的连通性和隔离性是由驱动来处理的。驱动通过实现特定网络类型的方式扩展了 Docker 网络栈,例如桥接网络和覆盖网络。
Docker 内置了若干驱动,通常被称作原生驱动或者本地驱动。例如 Bridge Driver、Host Driver、 Overlay Driver、 MacVLan Driver、 IPVLan Driver、 None Driver 等等。每个驱动负责创建其上所有网络资源的创建和管理。
三、常见网络类型
-
bridge
网络
bridge 驱动会在 Docker 管理的主机上创建一个 Linux 网桥。默认情况下,网桥上的容器可以相互通信。也可以通过 bridge 驱动程序配置,实现对外部容器的访问。Docker 容器的默认网络驱动.当我们需要多个容器在同一个 Docker 主机上通信时,桥接网络是最佳选择。 -
host
网络
对于独立容器,移除容器和 Docker 主机之间的网络隔离,并直接使用主机的网络。当网络堆栈不应该与 Docker 主机隔离,但是希望容器的其他资源被隔离时,主机网络是最佳选择。 -
container
网络
这个模式指定新创建的容器和引进存在的一个容器共享一个网络 ,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 ip,而是和一个指定的容器共享 ip,端口等,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。 -
none
网络
Docker 容器拥有自己的 Network Namespace,但是,并不为Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。容器完全网络隔离。 -
overlay
网络
借助 Docker 集群模块 Docker Swarm 搭建的跨 Docker Daemon 网络。将多个Docker 守护进程连接在一起,使集群服务能够相互通信。当我们需要运行在不同Docker 主机上的容器进行通信时,或者当多个应用程序使用集群服务协同工作时,覆盖网络是最佳选择。
另外,在 Docker 安装时,会自动安装一块 Docker 网卡称为 docker0
,它是一个网桥设备,主要用于 Docker 各容器及宿主机的网络通信。
四、Docker网络管理命令
docker network create
- 功能
创建自定义网络 - 语法
docker network create [OPTIONS] NETWORK
- 关键参数
-
-d, --driver
: 网络驱动 -
--gateway
: 网关地址 -
--subnet
: 表示网段的 CIDR 格式的子网 -
--ipv6
: 启用 ipv6
-
- 样例
#创建自定义网络
docker network create mynet1 --subnet=192.168.0.0/16
#查看网络列表
docker network ls
#查看网络详细信息
docker network inspect mynet1
docker network inspect
- 功能
查看网络详情 - 语法
docker network inspect [OPTIONS] NETWORK [NETWORK...]
- 关键参数
-
-f,--format
:指定格式
-
- 样例
#查看mynet1、mynet2网络详情
docker network inspect mynet1 mynet2
我们创建的容器默认使用的是桥接网络
docker network inspect bridge
docker network connect
- 功能
于将容器连接到网络。可以按名称或 ID 连接容器。 一旦连接,容器可以与同一网络中的其他容器通信。 - 语法
docker network connect [OPTIONS] NETWORK CONTAINER
- 关键参数
-
--ip
: 指定 IP 地址 -
--ip6
: 指定 IPv6 地址
-
- 样例
#创建自定义网络mynet3
docker network create mynet3 --subnet=10.2.0.0/16
#运行一个容器busybox
docker run -dit --name busybox1 busybox:1.36.0
docker network connect mynet3 busybox1
docker network inspect mynet3
docker network disconnect
- 功能
断开网络 - 语法
docker network disconnect [OPTIONS] NETWORK CONTAINER
- 关键参数
-
-f
:强制退出
-
- 样例
docker network inspect mynet3
docker network disconnect mynet3 busybox1
docker exec -it busybox1 sh
docker network prune
- 功能
删除不使用的网络 - 语法
docker network prune [OPTIONS]
- 关键参数
-
-f, --force
: 不提示
-
- 样例
docker network prune
docker network rm
- 功能
删除1个或多个网络 - 语法
docker network rm NETWORK [NETWORK...]
- 关键参数
-
-f
:强制退出
-
- 样例
docker network create mynet1
docker network create mynet2
docker network create mynet3
docker run -itd --name busybox2 busybox:1.36.0
docker network connect mynet3 busybox2
docker inspect mynet3
docker network rm mynet1 mynet2 mynet3
docker network ls
- 功能
列出网络 - 语法
docker network ls [OPTIONS]
- 别名
docker network list
- 关键参数
-
-f, --filter
:指定过滤条件 -
--format
:指定格式 -
--no-trunc
:不截断 -
-q, --quiet
:仅仅显示 id
-
- 样例
#返回名字为host的网络
docker network ls -f name=host
#以json形式返回网络列表
docker network ls --format json
#不截断返回列表
docker network ls --no-trunc
#仅仅返回网络id
docker network ls -q
网络命令基本操作
- 创建一个网络mynet6
docker network create mynet6 --subnet=10.15.0.0/16
- 创建容器时指定网络
docker run -itd --name busybox3 --network mynet6 busybox:1.36.0
docker inspect busybox3
docker inspect mynet6
- 先创建容器,再指定网络
docker run -itd --name busybox4 busybox:1.36.0
docker network connect mynet6 busybox4
- 将容器移除出网络并删除网络
五、网络详解
docker Bridge网络
网络介绍
Docker Bridge 网络采用内置的 bridge 驱动, bridge 驱动底层采用的是 Linux 内核中Linux bridge 技术。就网络而言, bridge 网络是在网络段之间转发流量的链路层设备,而网桥可以是在主机内核中运行的硬件设备或软件设备;就 Docker 而言,桥接网络使用软件网桥 docker0,它允许连接到同一网桥网络的容器进行通信,同时提供与未连接到该网桥网络容器的隔离。
Docker Container 的 bridge
桥接模式 可以参考下图:
默认情况下,创建的容器在没有使用 --network
参数指定要加入的 docker 网络时,默认都是加入 Docker 默认的单机桥接网络,即下面的 name 为 bridge
的网络。
默认的 bridge 网络会被映射到内核中为 docker0
的网桥上。Docker 默认的 bridge 网络和 Linux 内核中的 docker0 网桥是一一对应的关系。bridge 是 Docker 对网络的命名,而 docker0 是内核中网桥的名字。
生活案例
bridge 就像一个立交桥一样,有很多条路可以四通八达,每条路都连接了 2 个方向的通道。
操作案例
容器间的网络通信
- 创建两个容器检查二者是否网络互通
#创建两个容器
docker run -itd --name b1 busybox:1.36.0
docker run -itd --name b2 busybox:1.36.0
#分别进入两个容器
docker exec -it b1 sh
docker exec -it b2 sh
- 查看两个容器之间网络是否互通
- 停掉一个容器,看一下网络是否会自动断开
创建自定义bridge
在默认情况下, 我们创建的容器都会连接在 docker0 这个 bridge 上。那其实我们也可以创建一些自定义的 bridge,让运行的容器通过自定义 bridge 进行通信。
- 创建一个自定义bridge网络
docker network create mynet4
- 创建两个容器并加入刚刚创建的桥接网络
docker run -itd --name b3 --network mynet4 busybox:1.36.0
docker run -itd --name b4 --network mynet4 busybox:1.36.0
- 查看两个容器间是否网络互通
DNS解析
Docker 自定义桥接网络是支持通过 Docker DNS 服务进行域名解析的, 也就是说我们可以直接使用容器名进行通信,因为 DNS 服务可以解析容器名到 IP 地址的映射, 但是默认的 bridge 网络是不支持 DNS 的。
- 查看默认的bridge网络是否支持DNS解析
docker run -itd --name b51 busybox:1.36.0
docker run -itd --name b52 busybox:1.36.0
- 创建一个自定义网络,并创建两个新的容器加入进去
- 分别在两个容器中ping对方的名称, 发现可以ping通
因此,这里我们可以得出结论:默认的bridge网络不支持DNS域名解析,而自己创建的自定义bridge网络则支持。
端口暴露和转发
- 暴露方式
端口暴露有 2 种方式,在启动容器的时候添加端口参数,一种-P
暴露所有端口,一种是-p
,暴露指定端口-
-P
将指定的容器端口映射至主机所有地址的一个动态端口, ·“动态端口”指随机端口,具体的映射结果可使用 docker port 命令查看 -
-p <hostPort>:<containerPort>
将容器端口映射至指定的主机端口
-
- 端口转发
连接 bridge 网络的容器只能与连接在当前网络中的容器进行通信。如果一个容器想要对外提供一些网络服务的话,需要进行端口转发才可以实现。
端口转发将 Docker 容器的端口映射到宿主机的端口上,那么任何发送到宿主机该端口的流量,都会被转发到容器的端口中。如下图所示,两个容器内部均开放 80 端口,它们分别映射到宿主机的 8088 和 8089 端口, 即表示任何发送到 8088 端口的流量都会转发到 Container 1 容器的 80 端口, 发送到 8089 端口的流程都会转发到Container 2 容器的 80 端口。
docker run -d --name mynginx1 -p 8060:80 nginx:1.24.0
docker port mynginx1
docker Host 网络
网络介绍
Docker 容器运行默认都会分配独立的 Network Namespace
隔离子系统, 但是如果基于 host 网络模式,容器将不会获得一个独立的 Network Namespace, 而是和宿主机共用同一个 Network Namespace,容器将不会虚拟出自己的网卡, IP 等,而是直接使用宿主机的 IP 和端口。
连接到 host 网络的容器共享宿主机的网络栈,容器的网络配置与宿主机完全一样。我们可以通过 --network=host
指定使用 host 网络。
操作案例
- 创建两个容器,分别使用两种网络(桥接网络和host网络)
docker run -itd --name b61 busybox:1.36.0
docker run -itd --name b62 --network host busybox:1.36.0
- 分别查看两个容器网络的差异
这里我们需要注意一下,host网络的缺点就是宿主机的端口如果被占用,那么容器将不能使用该端口。
docker run -d --name mynginx2 --network host nginx:1.24.0
#查看容器日志信息
docker logs mynginx2
- 之前我们提到 bridge 网络在通信的时候需要进行端口转发以及 NAT 地址转换,这势必会消耗掉一些资源以及性能。
- 那么直接使用 host 网络最大的好处就是性能好,如果容器对网络传输效率有较高的要求,建议选择 host 网络。当然也会牺牲一些东西,比如要考虑端口冲突问题,其他服务已经被占用的端口就不能再使用了。
docker Container 网络
网络介绍
Docker Container
的 other container 网络模式是 Docker 中一种较为特别的网络的模式。之所以称为“other container 模式”,是因为这个模式下的 Docker Container,会使用其他容器的网络环境。之所以称为“特别”,是因为这个模式下容器的网络隔离性会处于 bridge 桥接模式与 host 模式之间。 Docker Container 共享其他容器的网络环境,则至少这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的容器存在网络隔离。
Docker Container 的 other container 网络模式实现逻辑如下:
- 查找 other container(即需要被共享网络环境的容器)的网络 namespace;
- 将新创建的 Docker Container(也是需要共享其他网络的容器)的 namespace,使用 other container 的 namespace
操作案例
- 创建两个容器,并将第二个容器加入第一个容器网络中。
docker run -itd --name b71 busybox:1.36.0
docker run -itd --name b72 --network container:b71 busybox:1.36.0
- 查看两个容器的IP信息
- 停掉第一个容器,查看情况
- 重启两个容器,容器网络得到恢复
在这种模式下的 Docker Container 可以通过 localhost 来访问 namespace 下的其他容器,传输效率较高。但是两个容器之间存在依赖,如果依赖容器重启了,会导致另外一个服务的网络不可用。
docker none 网络
网络介绍
none 网络
就是指没有网络。挂在这个网络下的容器除了 lo(本地回环),没有其他任何网卡。
操作案例
在运行容器的时候,可以通过 --network=none
参数来指定容器使用 none 网络。
- 创建一个容器,并加入none网络
docker run -itd --name b8 --network none busybox:1.36.0
文章来源:https://www.toymoban.com/news/detail-860189.html
- 在容器中查看IP信息
文章来源地址https://www.toymoban.com/news/detail-860189.html
- 针对一些对安全性要求比较高并且不需要联网的应用, 可以使用 none 网络, 比如生成随机密码, 避免生成密码被第三方获取。
- 一些第三方的应用可能需要 docker 帮忙创建一个没有网络的容器, 网络由第三方自己来配置。
到了这里,关于【Docker】Docker Network(网络)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!