Docker 网络

"醉也从容,悲也从容"


Docker Network

Docker 为什么需要网络管理?

网络出现的需求,就在于通信!Docker启动一个个容器,这些容器是什么??其本质就是一个个进程,进程需要通信,那么容器也就需要通信。容器之间的隔离是进程级别的,容器的网络默认与宿主机及其他容器都是相互隔离。

所以,我们就得考虑以下问题:
• 多个容器之间是如何通信的
• 容器和宿主机是如何通信的
• 容器和外界主机是如何通信的
• 容器需要更高的定制化网络(如定制特殊的集群网络、定制容器间的局域网) 应该如何实现

• 容器根本不需要网络的时候应该如何实现
......上述的这些问题都需要我们对容器的网络进行合理的管理才能解决,这就体现出了容
器网络管理的重要性。

Docker 网络架构简介

Docker 容器网络是为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作系统的网络环境中独立出来,形成容器自有的网络设备、IP 协议栈、端口套接字、IP路由表、防火墙等等与网络相关的模块。

为实现这种隔离性,Docker主要采用的架构由三部分组成:CNM、Libnetwork 和驱动。

👑 CNM

Docker 网络架构采用的设计规范是 CNM。CNM 中规定 了 Docker 网络的基础组成要素:

Sandbox、Endpoint、Network


• Sandbox: 提供了容器的虚拟网络栈,也即端口、套接字、IP 路由表、防火墙、DNS 配置等内容。主要用于隔离容器网络与宿主机网络,形成了完全独立的容器网络环境.
• Endpoint: 就是虚拟网络的接口,像普通网络接口一样,Endpoint 的主要职责是负责创建连接.
• Network: Docker 内部的虚拟子网,使得网络内的参与者能够进行通讯.

👑 Libnetwork

Libnetwork 是 CNM 的一个标准实现。采用 Go 语言编写(跨平台的),也是 Docker 所使用的库,Docker 网络架构的核心代码都在这个库中。

👑 驱动

驱动主要负责实现数据层相关内容,例如网络的连通性和隔离性是由驱动来处理的。驱动通过实现特定网络类型的方式扩展了 Docker 网络栈,例如桥接网络和覆盖网络。

常见的网络类型

💎 bridge 网络

Docker 容器的默认网络驱动。bridge 驱动会在 Docker 管理的主机上创建一个 Linux 网桥,默认情况下,网桥上的容器可以相互通信,也可以通过 bridge 驱动程序配置,实现对外部容器的访问。

💎 host 网络

对于独立容器,移除容器和 Docker 主机之间的网络隔离,并直接使用主机的网络。

💎 container 网络

这个模式指定新创建的容器和引进存在的一个容器共享一个网络 ,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 ip,而是和一个指定的容器共享 ip,端口等。

💎 none 网络

Docker 容器拥有自己的 Network Namespace,但是,并不为 Docker容器进行任何网络配置。

💎 overlay 网络
借助 Docker 集群模块 Docker Swarm 搭建的跨 Docker Daemon 网络。将多个Docker 守护
进程连接在一起,使集群服务能够相互通信。

💎 docker0

在 Docker 安装时,会自动安装一块 Docker 网卡称为 docker0,它是一个网桥设备,主要用于 Docker各容器及宿主机的网络通信。


Docker 网络命令详解

命令清单:

|---------------------------|-----------------------|--------------|
| 命令 | 别名 | 功能 |
| docker network create | | 创建网络 |
| docker network connect | | 连接网络 |
| docker network disconnect | | 断开网络 |
| docker network ls | docker network list | 列出网络 |
| docker network prune | | 删除不使用的网络 |
| docker network inspect | | 查看网络详情 |
| docker network rm | docker network remove | 删除 1 个或者多个网络 |

🧱 docker network create
语法:

bash 复制代码
# 创建自定义网络
docker network create [OPTIONS] NETWORK

OPTIONS:
-d, --driver:网络驱动
--gateway:网关地址
--subnet:表示网段的 CIDR 格式的子网
--ipv6:启用 ipv6

🧱 docker network inspect
语法:

bash 复制代码
# 查看网络详情
docker network inspect [OPTIONS] NETWORK [NETWORK...]

OPTIONS:
-f,--format:指定格式

🧱 docker network connect\disconnect
语法:

bash 复制代码
# 将容器连接到网络 
docker network connect [OPTIONS] NETWORK CONTAINER

# 指定要分配给容器网络接口的 IP 地址
OPTIONS:
--ip:指定 IP 地址
--ip6:指定 IPv6 地址

# 断开网络
docker network disconnect [OPTIONS] NETWORK CONTAINER

🧱 docker network prune
语法:

bash 复制代码
# 删除不使用的网络
docker network prune

OPTIONS:
-f, --force :不提示

🧱 docker network rm
语法:

bash 复制代码
# 删除 1 个或者多个网络
docker network rm NETWORK [NETWORK...]

OPTIONS:
-f:强制退出

🧱 docker network ls
语法:

bash 复制代码
# 列出网络
docker network ls [OPTIONS]

OPTIONS:
-f, --filter:指定过滤条件
--format:指定格式
--no-trunc:不截断
-q, --quiet :仅仅显示 id

网络命令基本操作

创建网络并指定 ip 地址段:

bash 复制代码
docker network create --subnet=172.20.0.0/16 mynetwork

查看创建的网络:

创建一个容器并加入网络:

bash 复制代码
docker run -itd --name mynginx 
    --network mynetwork nginx:1.24.0


docker container inspect mynginx

docker network inspect mynetwork

创建一个新的 nginx 容器 mynginx2,但是不加入我们的自定义网络:

bash 复制代码
docker run -itd --name mynginx2 nginx:1.23.0

查看该容器的网络配置,可以看到采用的是 docker0 桥:

我们将该容器加入到我们自己创建的网络:

bash 复制代码
docker network connect mynetwork mynginx2

再次查看我们的容器 2 的网络配置,可以看到它多了一个 mynetwork:

我们让容器二断开网络呢?

bash 复制代码
docker network disconnect mynetwork mynginx2

删除网络,可以看到网络被使用了,无法删除,停止正在使用这段网络的容器后,就可以删除了。


网络类型详解

🎁 docker Bridge 网络

网络介绍

Docker Bridge 网络采用内置的 bridge 驱动。bridge 驱动底层采用的是 Linux 内核中Linux bridge 技术。bridge 是 Docker 对网络的命名,而 docker0 是内核中网桥的名字。

就网络而言,bridge 网络是在网络段之间转发流量的链路层设备;就网桥而言可以是在主机内核中运行的硬件设备或软件设备。

就 Docker而言,bridge桥接网络使用软件网桥 docker0。从而允许连接到同一网桥网络的容器进行通信,同时提供与未连接到该网桥网络容器的隔离。

默认情况下,创建的容器在没有使用--network 参数指定要加入的 docker 网络时,都是加入 Docker 默认的单机桥接网络。

Docker 默认的 bridge 网络和 Linux 内核中的 docker0 网桥是一一对应的关系

操作案例

基于docker0的容器间的网络通信

多台主机该如何进行网络通信??对于两台主机而言,进行网络通信的法子很简单,就是双方插同一根网线。但遇到多台主机时,需要新增路由器/交换机。

把多台主机连接到路由器/交换机上, 通过路由器/交换机来达到交换数据, 即通信的目的。

容器之间的通信方式,与上述方法如出一辙。当我们创建容器,不明指 --network时,就会把该容器分配给 docker0这个网桥设备,此时这个docker0就可以类比上述的 交换机\路由器。我们接下来进行验证:

使用 busybox 镜像创建两个容器, 并且保持在后台运行:

我们获取两个容器的ip,可以使用docker network inspect查询:

bash 复制代码
"Containers": {
            "1754c377b55d9aa25f6784d5b86a5da6462a6974bba3a03b01fd43ccf231b2fb": {
                "Name": "busybox1",
                "EndpointID": "efeedbaeb1e0754d8831127e14a9ff930d81259c441049a1e38e4164f05c3cb5",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "383e713d9dd6d9032b9fc08877f305a23baea6b1eee505fc2dad027386d57900": {
                "Name": "busybox2",
                "EndpointID": "884768140d6e0ce97c4977d899f22669d300742cdedf00832b51a2ef8bbeebfd",
                "MacAddress": "02:42:ac:11:00:06",
                "IPv4Address": "172.17.0.6/16",
                "IPv6Address": ""
            },
}

也可以启用命令行的形式 ifconfig:

bash 复制代码
 docker container exec -it busybox1 ifconfig
 docker container exec -it busybox2 ifconfig

进入到两个容器中,尝试互相使用ping命令,结果发现它们能互相通信。

基于自定义bridge的容器间网络通信

在默认情况下, 我们创建的容器都会连接在 docker0 这个 bridge 上。那其实我们也可以创建一些自定义的 bridge,让运行的容器通过自定义 bridge 进行通信。

首先,我们创建一个新的bridge:

bash 复制代码
docker network create -d bridge new-bridge

-d,--driver 选项指定网络驱动程序

查看新bridge网段信息:

重新创建两个新的容器,并在创建之初给它们指定到 新bridge上。

bash 复制代码
docker run -itd --name busybox3 --network new-bridge busybox:latest
docker run -itd --name busybox4 --network new-bridge busybox:latest

我们查看new-bridge后,会发现新容器已经连接在里面了:

接下来,重复测试 busybox1\busybox2的动作,检查这两个同属new-bridge的容器,是否可以进行通信:

结果显然是我们预料的,它们能进行通信。

DNS 解析

Docker 自定义桥接网络是支持通过 Docker DNS 服务进行域名解析的。也就是说我们可以直接使用容器名进行通信,因为 DNS 服务可以解析容器名到 IP 地址的映射。但是默认的 bridge 网络是不支持 DNS 的。

其中,busybox1、2默认连接到 brige,busybox3、4则是连接到了自定义桥接 new-bridge。

默认桥段,是不能进行DNS的。

反观自定义桥段,则可以:

端口暴露和转发

• 端口暴露

端口暴露有 2 种方式:

🎉 -P:将指定的容器端口映射至主机所有地址的一个动态端口

🎉 -p<hostPort>:<containerPort>: 指定的主机端口 : 容器端口

• 端口转发

连接 bridge 网络的容器只能与连接在当前网络中的容器进行通信。如果一个容器想要对外提供一些网络服务的话,需要进行端口转发才可以实现。
端口转发将 Docker 容器的端口映射到宿主机的端口上,那么任何发送到宿主机该端口
的流量,都会被转发到容器的端口中。

例如,我们想要容器里的nginx服务能被浏览器访问到,所以在启动时会输入, "-p 80:80",这个过程就叫做端口暴露,当浏览器向我们的机器发起请求,将请求打到宿主机的80号端口时,这个请求又会被转发到,映射容器内部的端口,这个过程也就叫做端口转发。

🎁 docker Host 网络

网络介绍

Docker 容器运行默认都会分配独立的 Network Namespace 隔离子系统但是如果基于 host 网络模式,容器将不会获得一个独立的 Network Namespace。

此时,宿主机和容器共用同一个 Network Namespace。容器将不会虚拟出自己的网卡,IP 等等,而是直接使用宿主机的 IP 和端口。


连接到 host 网络的容器,共享宿主机的网络栈,容器的网络配置与宿主机完全一样。我们可以通过 --network=host 指定使用 host 网络。

操作案例

bash 复制代码
docker container run --name busybox -itd --network=host busybox:latest

查看busybox的网络配置信息:

这完完全全就是咱们宿主机的网络配置!

使用场景:

使用bridge网络在通信的时候需要进行端口转发以及 NAT 地址转换,这势必会消耗掉一些资源以及性能。直接使用 host 网络就没那么麻烦,性能也更好。但,选择host网络要考虑端口冲突问题,其他服务已经被占用的端口就不能再使用了。

🎁 docker Container 网络

网络介绍

docker container是一种较为特别的网络的模式,又称为"other container模式"。在这个模式下,Docker Container,会使用其他容器的网络环境。在这个模式下,容器的网络隔离性会处在bridge 桥接模式与 host 模式之间。

简单来说,就是一个容器使用另一个容器的网络配置。

操作案例

创建一个 busybox 容器:

bash 复制代码
docker run -itd --name netcontainer1 busybox

使用 netcontainer1 的网络创建另外一个容器:

bash 复制代码
docker run -itd --name netcontainer2 
    --network container:netcontainer1 busybox

进入两个容器,查看容器的 ip 信息,发现两个 ip 和 mac 完全一样:

我们停止容器 1,再次看下容器 2 的网络,发现 eth0 网卡消失了,只有一个本地网络了。

再次重启容器1和容器2然后可以看到容器2网络恢复。

使用场景:

在这种模式下的 Docker Container 可以通过 localhost 来访问 namespace 下的其他容器,传输效率较高。但是两个容器之间存在依赖,如果依赖容器重启了,会导致另外一个服务的网络不可用。

🎁 docker none 网络

网络介绍

none 网络就是指没有网络。挂在这个网络下的容器除了 lo(本地回环),没有其他任何网卡。

操作案例

在运行容器的时候,可以通过--network=none 参数来指定容器使用 none 网络:

bash 复制代码
docker container run -itd --name c3 
    --network none busybox
使用场景:

针对一些对安全性要求比较高并且不需要联网的应用, 可以使用 none 网络, 比如随机密码, 避免生成密码被第三方获取。

一些第三方的应用可能需要 docker 帮忙创建一个没有网络的容器, 网络由第三方自己来配置。


本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~

相关推荐
喝醉酒的小白1 小时前
几种K8s运维管理平台对比说明
运维·容器·kubernetes
明 庭1 小时前
通过 Docker 部署 pSQL 服务器的教程
服务器·docker·容器
字节全栈_kYu2 小时前
FastDFS实用笔记 (Docker 搭建环境 + 整合 SpringBoot)
spring boot·笔记·docker
破-风5 小时前
linux的用法
linux·运维·服务器
大耳朵土土垚8 小时前
【Linux】日志设计模式与实现
linux·运维·设计模式
学问小小谢8 小时前
第26节课:内容安全策略(CSP)—构建安全网页的防御盾
运维·服务器·前端·网络·学习·安全
yaoxin5211239 小时前
第十二章 I 开头的术语
运维·服务器
ProgramHan9 小时前
1992-2025年中国计算机发展状况:服务器、电脑端与移动端的演进
运维·服务器·电脑
马立杰12 小时前
H3CNE-33-BGP
运维·网络·h3cne
Linux运维老纪13 小时前
DNS缓存详解(DNS Cache Detailed Explanation)
计算机网络·缓存·云原生·容器·kubernetes·云计算·运维开发