Docker训练营(三)-Docker网络管理
Docker 网络是容器通信的基础设施,它使容器能够安全地进行互联互通。在 Docker 中,每个容器都可以被分配到一个或多个网络中,容器可以通过网络进行通信,就像物理机或虚拟机在网络中通信一样。
Docker 网络命令详解
在开始学习不同类型的网络之前,我们先来了解一下 Docker 的常用网络命令:
1 | 列出所有网络 |
网络类型及实践案例
1. Bridge 网络(桥接网络)
Bridge 网络是 Docker 的默认网络驱动程序。当你创建一个容器而不指定网络时,它会自动添加到默认的 bridge
网络中。Bridge 网络在单机环境下使用非常广泛,它通过软件网桥实现容器间的通信。
Bridge 网络的工作原理
Bridge 网络就像是 Docker 中的一个虚拟交换机,它在宿主机上创建一个名为 docker0 的网桥,
所有连接到这个网桥的容器都可以通过它进行通信。当你安装 Docker 时,会自动创建一个默认的 bridge 网络,
它使用 172.17.0.0/16 这个网段,所有未指定网络的容器都会自动连接到这个默认网络中。
不过,默认的 bridge 网络功能比较简单,容器之间只能通过 IP 地址互相访问,不支持通过容器名称来通信。
为了解决这个限制,Docker 提供了用户自定义 bridge 网络的功能。
当你创建自己的 bridge 网络时,连接到这个网络的容器就能获得更多便利的特性:容器之间可以通过名称相互访问,
网络隔离性更好,还可以随时将容器从网络中添加或移除。这就像是给容器们创建了一个独立的局域网,
既安全又方便管理。比如说,你可以把一个应用的前端、后端和数据库容器都放在同一个自定义 bridge 网络中,
它们就能通过容器名称轻松地相互通信,同时又与其他应用的容器网络保持隔离。
实践案例一:默认 Bridge 网络
让我们先来看看默认 bridge 网络的行为:
我们现构建一个装有 ping, curl 等指令的 nginx 镜像,方便我们在容器内容观察网络行为。
1 | 构建 nginx 镜像 |
1 | 查看默认 bridge 网络信息 |
Docker 默认的 bridge 网络存在通信限制:容器间只能通过易变的 IP 地址互相访问,无法使用固定的容器名称进行通信。
这种 IP 依赖会导致服务地址变更时需要人工调整配置,增加维护成本。通过创建自定义 bridge 网络,
容器可通过稳定的名称直接互访,这种自动化的服务发现机制正是 Docker Compose 实现容器编排的基础——编排工具会自动创建专用网络,
使多容器应用能够通过服务名称维持稳定的通信链路。
实践案例二:自定义 Bridge 网络
现在让我们看看自定义 bridge 网络的优势:
1 | 创建自定义 bridge 网络 |
docker network create ...
docker network create
: 创建一个新的 Docker 虚拟网络。--driver bridge
: 指定网络的驱动类型。bridge
(桥接) 是最常用的驱动。它会创建一个私有的内部网络,容器连接到这个网络上后,可以互相通信,也可以通过宿主机的网络接口与外部通信(如果需要的话)。你可以把它想象成你家里的路由器,它创建了一个局域网,所有连上 Wi-Fi 的设备(手机、电脑)都在这个局域网里,可以互相访问。
--subnet=172.20.0.0/16
: 指定这个网络的子网。- 这是一个 CIDR 地址块表示法。
172.20.0.0
是网络地址,/16
表示子网掩码,决定了这个网络里可以容纳多少个 IP 地址(这里是2^16 - 2 = 65534
个)。 - 作用: 当有容器加入这个网络时,Docker 会从这个
172.20.x.x
的地址池里给它分配一个私有 IP 地址。这让你可以对容器的 IP 地址有一个预期的规划。
- 这是一个 CIDR 地址块表示法。
--gateway=172.20.0.1
: 指定这个网络的网关地址。- 网关是这个虚拟局域网的“出口”。容器需要访问外部网络时,流量都会经过这个地址。通常我们会把网络地址段的第一个可用 IP (
.1
) 设置为网关。
- 网关是这个虚拟局域网的“出口”。容器需要访问外部网络时,流量都会经过这个地址。通常我们会把网络地址段的第一个可用 IP (
my-bridge-network
: 你给这个网络起的名字。
docker run ... --network my-bridge-network ...
--network my-bridge-network
: 这是docker run
命令中一个非常关键的参数。它的作用是,在容器启动时,就把它“插”到名为my-bridge-network
的网络上。- 执行完这两步后,
custom-container1
和custom-container2
就都成为了my-bridge-network
这个局域网的成员。它们各自会被分配一个 IP 地址,例如172.20.0.2
和172.20.0.3
。
docker exec -it custom-container1 curl http://custom-container2
这是最神奇的地方!
当你进入
custom-container1
内部,执行curl http://custom-container2
时,请求成功了。为什么可以用名字
custom-container2
?答案: Docker 为所有连接到自定义桥接网络 (
my-bridge-network
) 的容器提供了一个内置的 DNS 服务器。工作原理: 当你在
1
custom-container1
里尝试访问
1
custom-container2
这个主机名时:
custom-container1
的网络配置会将这个 DNS 查询发送到 Docker 内置的 DNS 服务器。- 这个 DNS 服务器维护着一张“域名-IP”映射表,其中包含了
my-bridge-network
网络上所有容器的名称和它们的内部 IP 地址。它知道"custom-container2"
对应的 IP 是172.20.0.3
(举例)。 - DNS 服务器将
172.20.0.3
这个地址返回给custom-container1
。 curl
程序拿到了这个 IP 地址,然后向172.20.0.3
的80
端口(http
默认端口)发起请求,从而成功访问到了custom-container2
里的 Nginx 服务。
✅【额外建议或常见错误】
- 自定义网络 vs. 默认网络:
- 当你安装完 Docker,它会自动创建一个名为
bridge
的默认网络。如果你docker run
时不指定--network
参数,容器就会被连接到这个默认网络上。 - 一个巨大的区别: 在默认的
bridge
网络上,这种基于容器名的自动服务发现是不支持的(或者说需要使用过时的--link
参数)。两个在默认网络里的容器无法直接通过名字互相访问。 - 因此,最佳实践是:只要你有两个或以上的容器需要互相通信,就应该为它们创建一个自定义的桥接网络,而不是使用默认网络。
- 当你安装完 Docker,它会自动创建一个名为
- 应用场景:
- 这个功能是 Docker Compose 和微服务架构的基石。想象一个典型的 Web 应用:一个
web-app
容器(跑着你的 Python/Java/Node.js 代码)和一个db
容器(跑着 MySQL/PostgreSQL)。 - 你只需要把它们都连接到同一个自定义网络
my-app-net
上,你的web-app
代码里连接数据库的地址就可以直接写成host="db"
,而不需要关心db
容器的具体 IP 是什么。这让配置变得极其简单和稳定。
- 这个功能是 Docker Compose 和微服务架构的基石。想象一个典型的 Web 应用:一个
- 调试技巧:
- 你可以使用
docker network inspect my-bridge-network
命令来查看网络的详细信息,包括哪些容器连接到了这个网络上,以及它们各自的 IP 地址。这在排查网络问题时非常有用。
- 你可以使用
实践案例三: 使用自定义 Bridge 网络演示 Web 应用与 Redis 通信
这个案例展示了在实际应用中如何使用自定义 bridge 网络:
首先,创建一个简单的 Web 应用:
1 |
|
然后创建网络并运行容器:
1 | 创建自定义 bridge 网络 |
现在可以测试应用了:
1 | 访问应用 |
docker exec -it redis-server redis-cli get hits
:在不进入容器交互式 Shell 的情况下,直接从宿主机终端对 redis-server
容器执行一条 Redis 客户端命令,以获取 hits
这个键(key)对应的值(value)。
redis-cli get hits
:- 这是真正要在
redis-server
容器内部执行的完整命令字符串。我们可以再把它拆分为三部分: redis-cli
: 这是 Redis 官方提供的命令行界面 (Command-Line Interface) 工具。它预装在官方的redis
镜像中,是你与 Redis 数据库交互的“遥控器”。get
: 这是redis-cli
的一个子命令,也是 Redis 数据库最基础的命令之一。它的作用是获取 (GET) 一个指定键 (key) 所存储的值 (value)。hits
: 这是你提供给get
命令的参数,即你想要查询的键(key)的名称。
- 这是真正要在
所以,整条命令串起来的含义就是:“Docker,请在 redis-server
容器里,帮我运行 redis-cli
工具,用它来 get
一个名叫 hits
的键的值,并把结果显示给我。”
清理环境:
1 | 停止并删除容器 |
2. Host 网络
Host 网络移除了容器和 Docker 主机之间的网络隔离,直接使用主机的网络。
特点:
- 最佳网络性能
- 直接使用主机的网络栈
- 没有网络隔离
- 端口直接绑定到主机上
实践案例:使用 Host 网络运行 Nginx 服务器
1 | 使用 host 网络运行 Nginx |
3. None 网络
None 网络完全禁用了容器的网络功能,容器在这个网络中没有任何外部网络接口。
特点:
- 完全隔离的网络环境
- 容器没有网络接口
- 适用于不需要网络的批处理任务
实践案例:使用 None 网络运行独立计算任务
1 | 运行一个计算密集型任务,不需要网络 |
4. Overlay 网络
Overlay 网络是 Docker 用于实现跨主机容器通信的网络驱动,主要用于 Docker Swarm 集群环境。
它通过在不同主机的物理网络之上创建虚拟网络,使用 VXLAN 技术在主机间建立隧道,从而实现容器间的透明通信。
在 Overlay 网络中,每个容器都会获得一个虚拟 IP,容器之间可以直接通过这个 IP 进行通信,
而不需要关心容器具体运行在哪个主机上。这种网络类型特别适合于微服务架构、分布式应用以及需要跨主机通信的容器化应用,
例如分布式数据库集群、消息队列集群等。Overlay 网络支持网络加密,能确保跨主机通信的安全性,
同时还提供了负载均衡和服务发现等特性,是构建大规模容器集群的重要基础设施。