Docker: Docker网络基础
最后更新:2026-08-26
容器网络是 Docker 最容易让人困惑的部分——直到你理解了"每个容器有自己的 localhost"。
1. 你将学到
- 四种网络模式的区别
- 自定义 bridge 网络与 DNS
- 容器间通信机制
- 网络隔离策略
- 端口映射原理
2. 一个开发者的真实故事
(1) 痛点:容器间 localhost 连不上
Alice 的 Web 应用和数据库在两个容器里,Web 容器用 localhost:5432 连不上数据库。她困惑了 2 小时:"明明数据库在 5432 端口监听,为什么连不上?"
(2) 容器网络隔离的解法
Bob 说:"每个容器有自己的 localhost。Web 容器的 localhost 是 Web 自己,不是数据库。要用容器名或自定义网络通信。"
BASH
# Create a custom network for inter-container communication
docker network create app-net
# Start containers on the same network
docker run -d --name db --network app-net -e POSTGRES_PASSWORD=secret postgres:15
docker run -d --name web --network app-net -p 8080:5000 myapp
# Web connects to db:5432 (not localhost:5432)
(3) 收益:网络问题 2 小时→5 分钟
理解了容器网络模型后,Alice 的网络问题从 2 小时排查降到 5 分钟配置。
3. Docker 四种网络模式
(1) 模式概览
graph TB
subgraph Bridge["Bridge Mode (default)"]
B1["Container A<br/>172.17.0.2"] --- B2["docker0 bridge<br/>172.17.0.1"]
B2 --- B3["Container B<br/>172.17.0.3"]
B2 --- B4["Host eth0<br/>via NAT"]
end
subgraph Host["Host Mode"]
H1["Container"] --- H2["Host Network Stack<br/>Shares all ports"]
end
subgraph None["None Mode"]
N1["Container<br/>Loopback only"]
end
subgraph Overlay["Overlay Mode"]
O1["Container A<br/>Host 1"] -.- O2["Container B<br/>Host 2"]
end
(2) 四种模式对比
| 维度 | Bridge | Host | None | Overlay |
|---|---|---|---|---|
| 隔离性 | 独立网络栈 | 共享主机网络 | 完全隔离 | 跨主机虚拟网络 |
| 端口映射 | 需要 -p |
不需要 | 不可用 | 内置路由 |
| 性能 | 中(NAT 开销) | 高(直接访问) | - | 中(VXLAN 封装) |
| DNS 解析 | 仅自定义 bridge | 无(共享主机) | 无 | ✅ 内置 |
| 跨主机 | ❌ | ❌ | ❌ | ✅ |
| 适用场景 | 单机多容器 | 高性能网络 | 安全隔离/调试 | Docker Swarm 集群 |
4. Bridge 网络详解
(1) 默认 bridge vs 自定义 bridge
| 维度 | 默认 bridge | 自定义 bridge |
|---|---|---|
| DNS 解析 | ❌ 只能用 IP | ✅ 用容器名通信 |
| 容器隔离 | 所有容器同一网络 | 按网络分组隔离 |
| 推荐度 | ⭐(兼容旧版) | ⭐⭐⭐(推荐) |
| 创建方式 | Docker 自动创建 | docker network create |
▶ 示例:创建自定义 bridge 网络(难度⭐)
BASH
# Create a custom bridge network
docker network create --driver bridge app-net
# Verify
docker network ls | grep app-net
docker network inspect app-net
▶ 示例:容器间 DNS 解析(难度⭐⭐)
BASH
# Start two containers on the same custom network
docker run -d --name db --network app-net \
-e POSTGRES_PASSWORD=secret postgres:15-alpine
docker run -d --name api --network app-net \
nginx:alpine
# DNS resolution: api can reach db by name
docker exec api ping -c 2 db
💻 输出:
TEXT
📖 仅展示
PING db (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.100 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.050 ms
📌 重点: 自定义 bridge 网络自动为每个容器注册 DNS 记录。容器名就是主机名——
db 解析为数据库容器的 IP。这就是为什么 Phase 1 的 LEMP 项目中 fastcgi_pass lemp-php:9000 能工作。
▶ 示例:网络隔离验证(难度⭐⭐)
BASH
# Create two separate networks
docker network create frontend-net
docker network create backend-net
# Frontend container
docker run -d --name web --network frontend-net nginx:alpine
# Backend container
docker run -d --name api --network backend-net nginx:alpine
# web CANNOT reach api (different networks)
docker exec web ping -c 2 -W 2 api
# Output: ping: bad address 'api'
# Connect web to backend-net (now it can reach api)
docker network connect backend-net web
docker exec web ping -c 2 api
# Output: PING api (172.19.0.2): 64 bytes
5. Host 网络模式
▶ 示例:Host 模式运行容器(难度⭐⭐)
BASH
# Run with host network (shares host's network stack)
docker run -d --name host-nginx --network host nginx:alpine
# No port mapping needed - nginx directly listens on host's port 80
curl http://localhost:80
⚠️ 注意: Host 模式下容器直接使用主机端口,不需要
-p 映射。但端口冲突风险高——如果主机 80 端口已被占用,容器启动会失败。生产环境慎用。
6. 端口映射原理
(1) 三种端口暴露方式
| 方式 | 语法 | 说明 |
|---|---|---|
-p host:container |
-p 8080:80 |
指定映射 |
-P |
-P |
随机映射到 EXPOSE 声明的端口 |
--network host |
--network host |
无需映射(共享主机网络) |
▶ 示例:docker network inspect 查看网络详情(难度⭐⭐)
BASH
# Inspect network configuration
docker network inspect app-net
💻 输出(节选):
TEXT
📖 仅展示
[
{
"Name": "app-net",
"Driver": "bridge",
"IPAM": {
"Config": [{"Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1"}]
},
"Containers": {
"a1b2c3d4...": {"Name": "db", "IPv4Address": "172.18.0.2"},
"e5f6a7b8...": {"Name": "api", "IPv4Address": "172.18.0.3"}
}
}
]
7. 完整示例:三层网络架构
BASH
# ============================================
# Complete walkthrough: Three-tier network architecture
# Frontend / Backend / Database isolation
# ============================================
# 1. Create three networks
docker network create frontend-net
docker network create backend-net
docker network create db-net
# 2. Start database (only on db-net)
docker run -d --name db \
--network db-net \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_DB=myapp \
postgres:15-alpine
# 3. Start API server (backend-net + db-net)
docker run -d --name api \
--network backend-net \
-e DATABASE_URL="postgresql://postgres:secret@db:5432/myapp" \
myapp-api:1.0
# Connect API to db-net so it can reach the database
docker network connect db-net api
# 4. Start Nginx (frontend-net + backend-net)
docker run -d --name web \
--network frontend-net \
-p 8080:80 \
-v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf \
nginx:1.25-alpine
# Connect Nginx to backend-net so it can reach the API
docker network connect backend-net web
# 5. Verify connectivity
docker exec web ping -c 1 api # web → api ✅
docker exec api ping -c 1 db # api → db ✅
docker exec web ping -c 1 -W 1 db # web → db ❌ (not on db-net)
# 6. Clean up
docker stop web api db
docker rm web api db
docker network rm frontend-net backend-net db-net
❓ 常见问题
Q 两个容器不在同一个网络能通信吗?
A 默认不能。每个网络是独立的隔离域。要让容器 A 访问网络 B 中的容器 C,需要用
docker network connect 将 A 加入网络 B。一个容器可以同时属于多个网络。Q host 网络模式有什么风险?
A 两个主要风险:① 端口冲突——容器直接监听主机端口,已有服务占用时启动失败;② 安全——容器可访问主机所有网络接口,包括 localhost 上的内部服务。仅在需要极致网络性能时使用 host 模式。
Q 容器 IP 会变吗?
A 会。容器重启后 IP 可能变化(尤其是非用户定义子网)。这就是为什么应该用容器名(DNS 解析)而不是 IP 地址通信。自定义 bridge 网络的 DNS 自动维护容器名→IP 的映射。
Q 怎么限制容器的网络访问?
A 三种方式:① 用多个网络隔离(推荐)——数据库只在 db-net,前端无法直接访问;② iptables 规则(高级);③
--icc=false 禁用默认 bridge 的容器间通信(不推荐,用自定义网络更好)。Q 跨主机的容器怎么通信?
A 单机 Docker 无法直接跨主机。方案:① Overlay 网络(需要 Docker Swarm 或手动配置 etcd);② 端口映射 + 主机 IP;③ 第三方网络插件(Weave/Calico)。Docker Swarm 的 Overlay 网络是最简单的跨主机方案(Phase 4 第 20 课)。
📖 小节
- 四种网络模式:Bridge(默认/推荐自定义)、Host(高性能)、None(隔离)、Overlay(跨主机)
- 默认 bridge 不支持 DNS,自定义 bridge 支持容器名 DNS 解析——始终用自定义 bridge
- 每个容器有自己的 localhost,容器间通信用容器名而不是 localhost
- 多网络隔离实现三层架构:Frontend ↔ Backend ↔ Database
docker network connect让容器加入多个网络- 端口映射
-p host:container将容器服务暴露到外部
📝 作业
- 基础题(难度⭐):创建自定义 bridge 网络,启动两个 Nginx 容器,验证容器名 DNS 解析(
docker exec A ping B)。 - 进阶题(难度⭐⭐):创建两个不同网络,各放一个容器,验证跨网络容器无法 ping 通。然后用
docker network connect连通。 - 挑战题(难度⭐⭐⭐):用
docker network inspect查看自定义网络的 IPAM 配置和容器列表,理解 Docker 内部网络路由机制。