docker 网络
docker 容器如何互相通信?如何暴露端口到外部?理解网络模式是容器化部署的基础。
一、docker 网络模型
1.1 为什么容器需要网络?
容器本质是隔离的进程,默认情况下: - 每个容器有独立的网络命名空间 - 容器间互不通信 - 容器无法从外部直接访问
1.2 四种内置网络模式
| 模式 | 命令 | 说明 |
|---|---|---|
| bridge | --network bridge |
默认模式,容器通过 docker0 网桥通信 |
| host | --network host |
直接共享宿主机网络,无隔离 |
| none | --network none |
无网络(纯隔离) |
| container | --network container:<id> |
复用另一个容器的网络栈 |
二、Bridge 模式(默认,重点)
2.1 原理
宿主机
├── docker0 网桥 (172.17.0.1)
├── 容器A (172.17.0.2) ←→ veth pair ←→ docker0
└── 容器B (172.17.0.3) ←→ veth pair ←→ docker0
- docker0 是一个虚拟网桥,在宿主机上创建
- 每个容器通过 veth pair(虚拟以太网对)连接到 docker0
- 容器通过 docker0 进行 NAT 转发访问外部网络
2.2 端口映射
# 基本映射
docker run -p 8080:80 nginx # 宿主机8080 → 容器80
# 指定监听地址
docker run -p 127.0.0.1:8080:80 nginx # 仅本机可访问
# 随机端口
docker run -P nginx # 随机映射所有 EXPOSE 端口
-p格式:[host_ip:]host_port:container_port
2.3 容器间通信
# 方式一:通过 IP(不推荐,IP 会变)
docker inspect my-nginx | grep IPAddress
# 方式二:通过 --link(已废弃)
docker run --link my-nginx:web my-app
# 方式三:自定义网络(推荐)
docker network create my-net
docker run -d --name app1 --network my-net nginx
docker run -d --name app2 --network my-net busybox
docker exec app1 ping app2 # ✅ 直接互通
三、Host 模式
docker run --network host nginx
- 容器共享宿主机的网络命名空间
- 没有独立的 IP 和端口,直接使用宿主机 IP:Port
- 性能最优(没有 NAT 开销),但网络隔离性最差
⚠️ Host 模式存在端口冲突风险,生产环境慎用。
3.1 Host 模式适用场景
- 对网络性能要求极高的场景(如网络基准测试)
- 容器需要直接监听宿主机大量端口的场景
- 不需要网络隔离的简单场景
四、自定义网络详解
4.1 为什么不用默认 bridge?
默认 bridge 的问题: - 容器间只能通过 IP 通信(名称不解析) - 不支持 DNS 自动发现 - 用户无法自定义子网和网关
4.2 创建自定义网络
# 创建桥接网络
docker network create --driver bridge my-bridge
# 创建指定子网的网络
docker network create --driver bridge --subnet 172.20.0.0/16 my-net
# 查看网络详情
docker network inspect my-net
# 删除网络
docker network rm my-net
4.3 跨容器通信
# 在同一自定义网络中的容器可以通过名称互相通信
docker run -d --name web --network my-net nginx
docker run -it --name app --network my-net alpine ping web
# ✅ 直接解析为容器名称,无需知道 IP
4.4 网络隔离
# 创建两个隔离网络
docker network create frontend-net
docker network create backend-net
# Web 容器仅加入 frontend-net(只能和前端通信)
docker run -d --name web --network frontend-net nginx
# DB 容器仅加入 backend-net(只能和后端通信)
docker run -d --name db --network backend-net mysql
# 两者完全隔离,无法互相访问
五、查看与诊断
5.1 常用命令
# 列出所有网络
docker network ls
# 查看网络详情(含哪些容器在上面)
docker network inspect bridge
# 查看网络统计
docker network stats
# 断开容器与网络
docker network disconnect bridge my-container
# 连接容器到网络
docker network connect my-net my-container
5.2 排查网络问题
# 1. 确认容器网络模式
docker inspect my-container | grep NetworkMode
# 2. 确认容器 IP
docker inspect my-container | grep IPAddress
# 3. 确认端口映射
docker port my-container
# 4. 在容器内部测试网络
docker exec my-container ping 8.8.8.8 # 测试外网连通性
docker exec my-container ping app-container # 测试容器间通信
docker exec my-container curl localhost:80 # 测试端口监听
六、常见面试题
- docker 有哪几种网络模式?默认是什么?
-
四种:bridge / host / none / container。默认是 bridge。
-
-p 和 -P 的区别?
-
-p指定宿主机端口映射;-P(大写)随机映射所有 EXPOSE 端口。 -
容器间如何互相通信?推荐哪种方式?
-
自定义网络 + 容器名称通信(DNS 自动解析),不依赖固定 IP。
-
Host 模式和 Bridge 模式有什么区别?
-
Host 共享宿主机网络栈,性能最好但无隔离;Bridge 有独立网络命名空间,通过 NAT 通信,隔离性更好。
-
什么是 veth pair?为什么 docker 要用它?
- veth pair 是一对虚拟以太网接口,数据从一个端发出、从另一端接收。docker 用它连接容器网络命名空间和宿主机网桥。