Docker 系列 | 06 - 容器网络:实现容器间通信
Docker 系列 | 06 - 容器网络:实现容器间通信
引言
在之前的文章中,我们学习了 Docker 镜像、容器和数据持久化。现在,我们需要解决一个关键问题:容器之间以及容器与外部世界如何进行通信?这就是 Docker 网络所负责的任务。
Docker 提供了一套强大的网络功能,允许您配置容器的网络连接方式,以满足各种应用场景的需求。本篇文章将详细解析 Docker 的几种网络模式,并指导您如何在实践中配置和管理容器网络。
Docker 网络基础概念
Docker 引擎默认使用桥接网络(Bridge Network)来连接容器,但同时也提供了其他几种网络模式。理解这些模式对于正确部署和管理容器化应用至关重要。
1. 虚拟网桥 (Bridge)
Docker 引擎在宿主机上会创建一个名为 docker0
的虚拟网桥(默认),并为每个容器分配一个独立的 IP 地址。容器通过这个虚拟网桥与宿主机通信,并通过宿主机进行外部网络访问。
特点:
- 默认模式:
docker run
不指定网络时,容器默认连接到bridge
网络。 - 网络隔离:不同容器之间默认可以通过 IP 地址互相访问(如果它们在同一个桥接网络中)。
- 端口映射:为了让外部世界访问容器内部的服务,通常需要通过
-p
或--publish
进行端口映射。
工作原理示意图:
+——————————————————-+
| 宿主机 |
| |
| +—————————————————+ |
| | docker0 网桥 | |
| | | |
| | +———–+ +———–+ +———–+ | |
| | | 容器 A | | 容器 B | | 容器 C | |
| | | (eth0: IP1) | | (eth0: IP2) | | (eth0: IP3) | |
| | +———–+ +———–+ +———–+ | |
| +—————————————————+ |
| ^ ^ ^ |
| | | | |
| 宿主机网络接口(如 eth0/en0) |
+——————————————————-+
(请您自行根据此描述绘制一个示意图,包含宿主机、docker0
网桥、连接到网桥的多个容器及其各自的 IP 地址,以及网桥连接到宿主机网络接口。)
2. 主机网络 (Host)
主机网络模式下,容器不会有自己独立的网络栈,而是直接共享宿主机的网络栈。容器的端口直接暴露在宿主机上,无需进行端口映射。
特点:
- 高性能:没有网络虚拟化的开销,性能接近直接在宿主机上运行。
- 无隔离:容器直接使用宿主机的网络,容器内服务的端口不能与宿主机上已占用的端口冲突。
- 端口映射无效:因为容器直接共享主机网络,所以
-p
选项不再有效。
使用场景:
- 对网络性能有极高要求的应用。
- 当容器内服务需要直接使用宿主机上的特定网络配置时。
语法:docker run --network host ...
示例:运行 Nginx 使用主机网络
1 | # 运行 Nginx 容器,直接使用宿主机网络 |
此时,您直接访问 http://localhost
(宿主机的 IP 地址) 就能看到 Nginx 页面,无需端口映射。
3. 无网络 (None)
无网络模式下,容器拥有自己的网络栈,但没有配置任何网络接口(除了 loopback 接口)。容器之间或容器与外部都无法通信。
特点:
- 完全隔离:容器没有任何网络连接。
- 安全:适用于只需要本地文件操作,不需要任何网络连接的容器。
语法:docker run --network none ...
4. 容器网络 (Container)
容器网络模式下,新创建的容器会共享另一个已有容器的网络命名空间。这两个容器会共享 IP 地址、端口等网络资源。
特点:
- 网络共享:两个容器拥有相同的 IP 地址和端口空间。
- 共同通信:一个容器内的进程可以访问另一个容器内进程通过
localhost
暴露的服务。
使用场景:
- 主应用容器和辅助代理/日志收集容器。
语法:docker run --network container:<name|id> ...
5. 自定义桥接网络 (User-defined Bridge Networks)
这是 Docker 网络中最推荐且最常用的模式,尤其是在多容器应用中。它允许您创建自己的桥接网络,提供比默认 docker0
网桥更好的隔离性和服务发现功能。
特点:
- 内置 DNS 服务发现:连接到自定义网络的容器可以通过服务名称直接互相通信,无需知道对方的 IP 地址。
- 更好的隔离:不同自定义网络中的容器相互隔离。
- 默认互联:同一个自定义网络中的容器默认可以直接互相访问。
- 与
docker-compose
完美集成:docker-compose
默认就会为服务创建自定义网络。
创建自定义网络:docker network create
1 | # 创建一个名为 my-app-net 的自定义桥接网络 |
示例:使用自定义网络运行应用和数据库
运行 MySQL 容器并连接到自定义网络
1
2
3
4
5docker run -d \
--name my-mysql-db \
--network my-app-net \
-e MYSQL_ROOT_PASSWORD=mysecretpassword \
mysql:8.0运行 Flask 应用容器并连接到同一个自定义网络
1
2
3
4
5
6# 假设你的 Flask 应用配置中,数据库地址是 'my-mysql-db'
docker run -d \
-p 5000:5000 \
--name my-flask-app \
--network my-app-net \
my-flask-app:1.0
现在,my-flask-app
容器可以通过 my-mysql-db
这个服务名称(而不是 IP 地址)来访问 MySQL 数据库,Docker 会自动进行 DNS 解析。
端口映射 (Port Mapping)
端口映射是让宿主机或其他外部设备访问容器内部服务的方法。它将宿主机的一个端口转发到容器的某个端口。
语法:-p <host_port>:<container_port>
或 --publish <host_port>:<container_port>
- **
<host_port>
**:宿主机上暴露的端口。 - **
<container_port>
**:容器内部服务监听的端口。
示例:
1 | # 将容器的 80 端口映射到宿主机的 8080 端口 |
管理网络:常用命令
- **
docker network ls
**:列出所有 Docker 网络。 - **
docker network create <name>
**:创建一个自定义网络。 - **
docker network rm <name>
**:删除一个网络。 - **
docker network inspect <name>
**:查看网络的详细信息,包括连接到该网络的容器的 IP 地址。 - **
docker network connect <network> <container>
**:将一个运行中的容器连接到指定网络。 - **
docker network disconnect <network> <container>
**:将一个容器从指定网络断开。
结语
本篇文章深入探讨了 Docker 的几种网络模式,包括默认的桥接网络、主机网络、无网络、容器网络,以及最推荐的自定义桥接网络。理解并灵活运用这些网络模式,是构建复杂多容器应用的基础。端口映射也是将容器服务暴露给外部的关键。
在下一篇文章中,我们将对目前所学的 Docker 基础命令进行一个汇总和速查,帮助您更高效地记忆和使用这些命令。