容器不仅仅是孤立的运行环境,它们需要相互通信,也需要与外部世界进行交互。Docker 通过强大而灵活的网络子系统来实现这一点。理解 Docker 的不同网络模式,是构建和部署复杂多容器应用的关键。本节将深入探讨 Docker 原生提供的四种网络模式以及强烈推荐使用的自定义网络
思维导图


一、Bridge 模式 - 默认的网络
bridge 模式是 Docker 默认使用的网络模式。当你运行一个容器而不指定 --network 参数时,它就工作在这个模式下。
Docker 在宿主机上 默认创建一个名为
docker0 的 虚拟网桥,==用来让主机和容器在同一子网内通过 IP 直接通信==。每个容器都会 被分配一个 独立的网络命名空间和一个连接到 docker0 的 私有IP地址。 Bridge 模式特性
| 特性 | 说明 |
| :--- | :--- |
| 网络隔离 | 默认提供良好的网络隔离,每个容器有自己的网络栈。 |
| 容器间通信 | 连接到 同一网桥的容器,可以通过 彼此的私有IP地址通信。 |
| 外部访问 | 必须使用
-p 或 -P 进行 端口映射,才能从外部访问容器服务。 | 代码示例:
bash # 1. 启动三个 Nginx 容器,分别映射到宿主机的不同端口 docker run -d --name nginx1 -p 8081:80 nginx docker run -d --name nginx2 -p 8082:80 nginx docker run -d --name nginx3 -p 8083:80 nginx # 2. 查看容器的私有 IP docker inspect nginx1 | grep "IPAddress" docker inspect nginx2 | grep "IPAddress" docker inspect nginx3 | grep "IPAddress" # 3. 在宿主机上查看 docker0 网桥和 veth 接口 ip addr show docker0 ip link show | grep veth # 4. 查看 veth 和 docker0 的桥接关系 brctl show docker0 # 5. 测试同一子网直连通信 # 从宿主机 ping 容器 ping -c 2 172.17.0.2 # 假设 nginx1 ping -c 2 172.17.0.3 # 假设 nginx2 # 容器之间互 ping docker exec -it nginx2 ping -c 2 172.17.0.2 docker exec -it nginx3 ping -c 2 172.17.0.3 # 6. 测试端口映射访问 curl http://localhost:8081 curl http://localhost:8082 curl http://localhost:8083 ## 二、Host 模式 - 共享宿主机网络
host 模式下,容器 不再拥有自己 独立的网络命名空间,而是 直接共享宿主机的 网络栈。 Host 模式特性总结
| 特性 | 说明 |
| :--- | :--- |
| 网络共享 | 容器 直接使用宿主机的IP地址和网络配置。 |
| 性能 | 网络性能最高,因为没有NAT转换的开销。 |
| 端口 | 无需端口映射 (
-p 无效)。容器监听的端口 直接暴露在宿主机上。 | | 缺点 | 牺牲了网络隔离性,容易发生 端口冲突。 |
代码示例:
bash # 使用 host 模式启动一个 Nginx 容器 docker run -d --name nginx-host --network host nginx # 在宿主机上直接访问 localhost:80 curl http://localhost ## 三、None 模式 - 完全隔离
none 模式为容器 创建一个独立的 网络命名空间,但 不为其进行任何 网络配置。 None 模式特性总结
| 特性| 说明 |
| :--- | :--- |
| 网络配置 | 容器内 仅有一个
lo (loopback) 回环网卡。 | | 隔离性 | 完全的网络隔离,无法与外部、宿主机或其他容器通信。 |
| 适用场景 | 完全不需要网络连接的任务,如 批量计算或 高安全需求的任务。 |
代码示例:
bash # 使用 none 模式启动一个 tomcat 容器 docker run -d -p 8085:8080 --name my_tomcat02 --network none tomcat # 在宿主机查看容器网络配置 docker inspect my_tomcat02 | tail -20 ## 四、Container 模式 - 共享网络
container 模式允许一个 新创建的容器共享 另一个已存在容器的 网络命名空间。 Container 模式特性总结
| 特性 | 说明 |
| :--- | :--- |
| 网络共享 | 新容器 与目标容器共享同一个IP、端口、路由等。 |
| 通信 | 两个容器之间可以通过
localhost 直接通信。 | | 适用场景 | “边车 (Sidecar)”模式,如 主应用与 网络监控或 日志收集容器的组合。 |
代码示例:
bash # 1. 先启动一个主容器 (目标容器) docker run -d --name main-app nginx # 2. 启动一个边车容器,共享 main-app 的网络 docker run -it --name sidecar --network container:main-app busybox # 3. 在 sidecar 容器的 shell 内部,通过 localhost 访问 main-app 的 Nginx 服务 wget -qO- http://localhost ## 五、自定义网络 - 最佳实践
在 生产环境或 多容器应用中, 强烈推荐创建和使用 自定义的 bridge 网络。
自定义网络核心优势
| 优势 | 说明 |
| :--- | :--- |
| 自动DNS解析 | 最大的优点。容器间可以通过 容器名称直接通信,无需关心IP地址。 |
| 更佳网络隔离 | 不同自定义网络之间默认是 隔离的,提供了更安全的环境。 |
常用网络管理命令
| 命令 | 作用 |
| :--- | :--- |
|
docker network create <name> | 创建一个自定义网络。 | |
docker network ls | 列出所有网络。 | |
docker network inspect <name> | 查看网络详情,包括连接的容器。 | |
docker network connect <net> <cont> | 将 已运行的容器连接到网络。 | |
docker network disconnect <net> <cont> | 断开容器与网络的连接。 | |
docker network rm <name> | 删除一个自定义网络。 | 代码示例 (容器名通信):
bash # 1. 创建自定义网络 docker network create my-app-network # 2. 再创建一个测试网络 docker network create test # 3. 查看当前所有网络 docker network ls # 4. 查看 bridge 网络详情 docker network inspect bridge # 5. 将容器 my-nginx 连接到 test 网络 docker network connect test my-nginx # 6. 查看 my-nginx 的网络配置(此时有 bridge 和 test 两个网络) docker inspect my-nginx # 7. 将 my-nginx 从 test 网络移除 docker network disconnect test my-nginx # 8. 再次查看 my-nginx 的网络配置(只剩下 bridge) docker inspect my-nginx ---
## 练习题
题目一:默认网络模式
当你执行 docker run nginx 时,该容器默认会连接到哪个网络?
题目二:Bridge 模式通信
你有两个以默认 bridge 模式运行的容器 container-a 和 container-b。如何在 container-a 中访问 container-b?
题目三:Host 模式特性
使用 host 网络模式启动一个容器后,如何查看该容器的IP地址?
题目四:Host 模式端口
如果一个容器以 host 模式运行,并且其内部的应用监听 8080 端口,你需要使用 docker run 的哪个参数来暴露这个端口给宿主机?
题目五:None 模式应用
描述一个适合使用 none 网络模式的具体场景。
题目六:Container 模式核心
在 container 模式下,两个容器共享了什么?它们之间最简单的通信方式是什么?
题目七:自定义网络优势
相比默认的 bridge 网络,创建自定义 bridge 网络的两个主要优势是什么?
题目八:自定义网络创建
写出一条命令,创建一个名为 backend-net 的自定义 bridge 网络。
题目九:连接到自定义网络
如何启动一个新的 redis 容器,命名为 cache,并将其直接连接到 backend-net 网络?
题目十:容器名解析
假设 cache 容器和一个名为 api-server 的应用容器都连接到了 backend-net。在 api-server 容器内部,应该使用哪个主机名来连接 cache 容器?
题目十一:动态连接网络
一个名为 legacy-app 的容器已经在默认的 bridge 网络中运行。如何将其也连接到 backend-net 网络,使其可以与 cache 和 api-server 通信?
题目十二:网络隔离
你有两个自定义网络 frontend-net 和 backend-net。一个名为 webapp 的容器只连接到 frontend-net,一个名为 database 的容器只连接到 backend-net。webapp 容器是否能直接通过容器名访问 database 容器?
题目十三:查看网络中的容器
如何查看 backend-net 网络中当前连接了哪些容器?
题目十四:网络模式选择
你需要部署一个对网络延迟极其敏感、性能要求极高的应用,并且可以接受较低的安全隔离性。你应该优先考虑哪种网络模式?
题目十五:断开网络连接
写出一条命令,将 legacy-app 容器从 backend-net 网络中断开连接。
答案与解析
答案一:
默认的 bridge 网络
答案二:
首先使用 docker inspect container-b 查找其私有IP地址,然后在 container-a 内部使用该IP地址进行访问 (例如 ping <ip_address_of_b>)。
解析: 默认 bridge 网络不支持容器名DNS解析,只能通过IP地址通信
答案三:
容器没有自己的独立IP地址,它共享宿主机的IP。你可以通过在宿主机上执行 ip a 或 ifconfig 来查看。
答案四:
不需要任何参数。
答案五:
一个执行密码破解或科学计算的容器。这类任务只需要CPU和内存资源,完全不需要网络连接,使用 none 模式可以最大化安全隔离。
答案六:
它们共享同一个网络命名空间 (IP地址、端口、路由表等)。最简单的通信方式是通过 localhost。
答案七:
1.自动DNS解析:可以通过容器名直接通信。2. 更好的网络隔离:不同自定义网络之间默认是隔离的。
答案八:
docker network create backend-net 答案九:
docker run -d --name cache --network backend-net redis 答案十:
应该使用主机名 cache。
答案十一:
docker network connect backend-net legacy-app 解析:
docker network connect允许将一个正在运行的容器连接到一个或多个网络。
答案十二:
不可以。
解析: 容器默认只能与连接在相同网络中的其他容器通信。要让它们通信,需要将其中一个容器也连接到另一个网络上。
答案十三:
docker network inspect backend-net 答案十四:
应优先考虑 host 模式。
解析:
host模式消除了网络地址转换 (NAT) 的开销,提供了最佳的网络性能,代价是牺牲了隔离性。
答案十五:
docker network disconnect backend-net legacy-app