Docker 容器网络详解
Docker 提供强大的网络功能,支持多种网络模式,理解这些模式是搭建容器集群和微服务架构的基础。本文详细介绍 Docker 的四种内置网络模式和端口映射。
网络模式概述
Docker 安装后自动创建三个网络:bridge、host、none。可通过以下命令查看:
bash
docker network ls
# 输出示例
# NETWORK ID NAME DRIVER SCOPE
# 7f4b9b5a6c2d bridge bridge local
# 8a1b3c4d5e6f host host local
# 9b2c4d6e8f0a none null local1
2
3
4
5
6
7
2
3
4
5
6
7
四种网络模式
1. bridge 模式(默认)
bridge 是 Docker 的默认网络模式。容器连接到这个虚拟网桥,拥有独立的网络命名空间。
bash
# 启动一个使用默认bridge网络的容器
docker run -d --name container1 nginx
# 查看容器IP
docker inspect -f '{{.NetworkSettings.IPAddress}}' container1
# 通常是 172.17.0.x
# 查看bridge网络详情
docker network inspect bridge1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
工作原理:
宿主机
┌─────────────────────────────────┐
│ docker0 网桥 (172.17.0.1) │
│ ┌───────────┐ ┌───────────┐ │
│ │容器1 │ │容器2 │ │
│ │172.17.0.2│ │172.17.0.3│ │
│ └───────────┘ └───────────┘ │
│ ↑ NAT │
│ ┌────────┴────────┐ │
│ │ eth0 (物理网卡) │ │
│ └─────────────────┘ │
└─────────────────────────────────┘1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
同一 bridge 网络的容器互通:
bash
# 容器间可以用容器名直接通信(通过嵌入式 DNS)
docker run -d --name app1 nginx
docker run -d --name app2 nginx
# app2 可以 ping app1
docker exec app2 ping -c 3 app1
# 输出: PING app1 (172.17.0.2) 56(84) bytes of data.1
2
3
4
5
6
7
2
3
4
5
6
7
自定义 bridge 网络(推荐):
bash
# 创建自定义bridge网络
docker network create --driver bridge my-network
# 创建时指定子网和网关
docker network create --driver bridge \
--subnet=192.168.10.0/24 \
--gateway=192.168.10.1 \
my-network
# 将容器连接到自定义网络
docker run -d --name app1 --network my-network nginx
# 将已运行的容器连接到网络
docker network connect my-network container1
# 断开容器网络连接
docker network disconnect my-network container11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
自定义 bridge vs 默认 bridge 的区别:
- 自定义 bridge 支持容器名 DNS 解析
- 自定义 bridge 可独立管理(创建/删除/配置)
- 自定义 bridge 容器在移除后自动从网络断开
- 自定义 bridge 可配置更多选项(IP范围、网关等)
2. host 模式
容器直接使用宿主机的网络命名空间,没有独立的网络隔离。
bash
# 启动使用 host 网络的容器
docker run -d --name web --network host nginx1
2
2
特点:
- 容器与宿主机共享网络栈
- 容器可以使用宿主机的端口(无需
-p映射) - 网络性能最好(无 NAT 转发)
- 端口冲突风险高
bash
# 宿主机已占用80端口时,host模式容器会冲突
# 解决方案:避免使用 host 模式,或做好端口规划
# 验证host模式
docker run -d --name test --network host nginx
netstat -tlnp | grep :80 # 在宿主机上查看,nginx实际在监听1
2
3
4
5
6
2
3
4
5
6
适用场景:
- 对网络性能要求极高(接近物理机性能)
- 容器需要使用所有宿主机端口
- K8s/Docker Swarm 等编排工具的某些场景
3. container 模式
容器共享另一个容器的网络命名空间,相当于"网络挂载"到另一个容器。
bash
# 启动一个基础容器
docker run -d --name myredis redis
# 新容器使用 myredis 的网络栈
docker run -d --name app --network container:myredis nginx
# 此时 app 和 myredis 共享同一网络命名空间
# app 可以直接用 localhost 访问 myredis 的端口
docker exec app nc -zv localhost 63791
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
典型用法: 同一个服务的主进程和辅助进程共享网络:
bash
# nginx + nginx-proxy-manager 共享网络
docker run -d --name proxy nginx-proxy-manager
docker run -d --name webapp \
--network container:proxy \
mywebapp1
2
3
4
5
6
2
3
4
5
6
4. none 模式
容器有独立的网络命名空间,但不做任何网络配置(无网卡、无路由)。
bash
docker run -d --name isolated --network none nginx
# 进入容器查看网络
docker exec isolated ip a
# 输出只有 loopback: lo1
2
3
4
5
2
3
4
5
适用场景:
- 不需要网络的服务(如离线数据处理)
- 只需要本地存储的批处理任务
- 高度安全隔离环境
端口映射
bridge 模式下,容器默认无法从外部访问,需要通过 -p 参数将容器端口映射到宿主机。
基本映射语法
bash
# 宿主机端口:容器端口
docker run -d -p 8080:80 --name web nginx
# 访问宿主机 8080 端口 = 访问容器 80 端口
# 映射到指定IP和端口
docker run -d -p 127.0.0.1:8080:80 nginx
# 只有本机可以访问(适合本地开发)
# 映射到随机端口
docker run -d -p 80 nginx
# Docker 自动分配一个高位端口(通常 32768+)
# 同时映射多个端口
docker run -d -p 80:80 -p 443:443 --name web nginx
# UDP 端口映射
docker run -d -p 53:53/udp --name dns bind9
# 指定协议
docker run -d -p 8080:80/tcp -p 8080:80/udp nginx1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
端口映射原理
外部请求 → 宿主机:8080 → docker0 NAT → 容器:801
Docker 会在 iptables 中添加 NAT 规则,实现端口转发。
查看端口映射
bash
# 查看容器端口映射
docker port web
# 查看详细映射
docker inspect -f '{{range $k, $v := .NetworkSettings.Ports}}{{$k}} -> {{range $v}}{{.HostIp}}:{{.HostPort}}{{end}}{{end}}' web
# 列出容器及其映射
docker ps --format "table {{.Names}}\t{{.Ports}}"1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
宿主机端口范围
bash
# 默认 Docker 使用 32768-60999 范围的随机端口
# 可通过配置修改:
# /etc/docker/daemon.json
{
"ip-forward": true,
"ip-masquerade": true,
"default-address-pools": [
{"base": "172.80.0.0/16", "size": 24}
]
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
网络相关命令
bash
# 查看所有网络
docker network ls
# 查看网络详情
docker network inspect bridge
# 创建网络
docker network create --driver bridge mynet
# 删除网络(先断开所有容器)
docker network rm mynet
# 清理未使用网络
docker network prune
# 将容器连接到网络
docker network connect mynet container1
# 断开容器网络
docker network disconnect mynet container1
# 查看容器使用的网络
docker inspect -f '{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}' container11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
跨主机网络通信
Docker Swarm 覆盖网络(Overlay)
bash
# 初始化Swarm(成为manager节点)
docker swarm init
# 创建覆盖网络
docker network create -d overlay my-overlay-net
# 在Swarm集群中,不同主机上的容器可通过覆盖网络通信
# 无需额外配置,Docker 自动处理跨主机隧道1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Macvlan 模式(直接连接物理网络)
bash
# 创建 macvlan 网络(连接物理网卡 eth0)
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
my-macvlan
# 容器获得物理网络IP,像物理机一样直接暴露在网络中
docker run -d --network my-macvlan --name web nginx1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
IPvlan 模式
bash
# IPvlan L2 模式(与 macvlan 类似但无广播问题)
docker network create -d ipvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
-o ipvlan_mode=l2 \
my-ipvlan1
2
3
4
5
6
7
2
3
4
5
6
7
常用网络故障排查
容器无法连接外部网络
bash
# 检查 iptables 规则
sudo iptables -t nat -L -n | grep DOCKER
# 检查 IP 转发是否开启
cat /proc/sys/net/ipv4/ip_forward
# 手动开启(如果关闭)
sudo sysctl -w net.ipv4.ip_forward=1
# 重启 Docker 服务
sudo systemctl restart docker1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
容器间无法通过名字通信
bash
# 默认bridge不支持名字解析
# 解决方案1: 使用自定义bridge
docker network create mynet
docker run -d --name app1 --network mynet nginx
docker run -d --name app2 --network mynet nginx
docker exec app2 ping app1 # 可以解析
# 解决方案2: 使用 --link(已废弃,不推荐)
docker run -d --link app1:app1 --name app2 nginx1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
端口映射不生效
bash
# 检查端口是否被占用
sudo netstat -tlnp | grep :8080
# 检查容器是否在运行
docker ps | grep web
# 检查容器日志
docker logs web
# 确认监听地址
# nginx 配置中确保监听 0.0.0.0 而非 127.0.0.11
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
DNS 解析问题
bash
# 使用自定义 DNS
docker run -d --dns 8.8.8.8 --name web nginx
# 添加 hosts 条目
docker run -d --add-host myhost:192.168.1.100 nginx
# 查看容器 DNS 配置
docker exec web cat /etc/resolv.conf1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
网络性能优化
bash
# 开启 host 网络(获得最佳性能,无NAT)
docker run -d --network host nginx
# 使用 macvlan/ipvlan(容器获得物理网络IP,性能接近物理机)
# 适用于对网络延迟敏感的应用
# 减少网络转发层级
# 同一主机上容器通信优先用 container 模式或自定义 bridge
# 调整 Docker 网桥 MTU
docker network create -d bridge --opt "com.docker.network.bridge.mtu=1400" mynet1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
小结
| 模式 | 说明 | 隔离性 | 性能 | 适用场景 |
|---|---|---|---|---|
| bridge | 虚拟网桥+NAT | 独立网络栈 | 一般 | 默认、开发、多数生产场景 |
| host | 共享宿主机网络 | 无隔离 | 最好 | 高性能、对端口无特殊要求 |
| container | 共享另一容器网络 | 依赖被共享方 | 最好 | 同主机多容器协作 |
| none | 无网络配置 | 完全隔离 | 无网络 | 离线任务、极安全环境 |
| overlay | 跨主机隧道 | 集群级 | 较好 | Docker Swarm 多主机 |
| macvlan | 物理网络直通 | 物理网络级 | 最好 | 需要容器暴露在物理网络 |
根据实际需求选择合适的网络模式,是构建可靠容器架构的关键一步。
[[返回 Docker 首页|../index]]