基础 掌握Docker网络模型,理解端口映射、网络模式与容器间通信
Docker使用Linux网络命名空间(Network Namespace)为每个容器提供独立的网络栈。容器通过虚拟网桥与外部通信:
# 1. 指定IP:主机端口:容器端口
docker run -d --name web1 -p 127.0.0.1:8080:80 nginx:alpine
# 仅本机可访问 ✅ 验证通过
# 2. 主机端口:容器端口(所有网卡)
docker run -d --name web2 -p 8081:80 nginx:alpine
# 所有网络接口可访问 ✅ 验证通过
# 3. 容器端口(随机分配主机端口)
docker run -d --name web3 -p 80 nginx:alpine
docker port web3
# 80/tcp -> 0.0.0.0:32768
# 4. 多端口映射
docker run -d --name web4 \
-p 8082:80 \
-p 8443:443 \
nginx:alpine
# ✅ 验证通过:同时映射HTTP和HTTPS
# -P 大写:映射所有EXPOSE端口到随机端口
docker run -d --name web5 -P nginx:alpine
docker port web5
# 80/tcp -> 0.0.0.0:32769
# 查看Docker创建的NAT规则
iptables -t nat -L DOCKER -n 2>/dev/null | head -10
# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80
# 查看端口映射详情
docker inspect web2 --format '{{json .NetworkSettings.Ports}}' | python3 -m json.tool
# {"80/tcp": [{"HostIp": "0.0.0.0", "HostPort": "8081"}]}
ss -tlnp | grep <端口> 检查端口占用。
| 模式 | 参数 | 特点 | 适用场景 |
|---|---|---|---|
bridge | --network bridge | 默认模式,独立网络栈 | 大多数容器 |
host | --network host | 共享宿主机网络栈 | 性能敏感应用 |
none | --network none | 无网络,只有lo接口 | 安全隔离任务 |
container | --network container:<id> | 共享另一容器网络 | sidecar模式 |
overlay | --network overlay | 跨主机通信 | Swarm/集群 |
# 创建自定义bridge网络(推荐)
docker network create --driver bridge \
--subnet 172.20.0.0/16 \
--gateway 172.20.0.1 \
my-net
# 在自定义网络中运行容器
docker run -d --name app-web --network my-net nginx:alpine
docker run -d --name app-api --network my-net alpine:latest \
sh -c "while true; do sleep 3600; done"
# 容器间通过容器名通信(自动DNS)
docker exec app-api ping -c 2 app-web
# PING app-web (172.20.0.2): 56 data bytes
# 64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.100 ms
# ✅ 验证通过:容器名DNS解析正常
# Host模式——直接使用宿主机网络
docker run -d --name host-web --network host nginx:alpine
# 容器直接监听宿主机80端口,无需-p映射
# 验证
curl -s http://localhost:80 | head -5
# ...
# 注意:host模式下 -p 参数无效
docker run -d --name host-test --network host -p 9090:80 nginx:alpine
docker logs host-test 2>&1 | head -3
# WARNING: Published ports are discarded when using host network mode
# 无网络容器
docker run -it --rm --network none alpine:latest sh -c "ip addr"
# 1: lo: <LOOPBACK,UP> mtu 65536
# inet 127.0.0.1/8 scope host lo
# 只有回环接口,无eth0 ✅
# 无法访问外部
docker run --rm --network none alpine:latest ping -c 1 8.8.8.8
# ping: bad address '8.8.8.8' ✅ 无外部网络
# 主容器
docker run -d --name main-app -p 8083:80 nginx:alpine
# Sidecar容器共享主容器网络
docker run -d --name sidecar \
--network container:main-app \
alpine:latest sh -c "while true; do sleep 3600; done"
# sidecar看到的是main-app的网络栈
docker exec sidecar ip addr
# 与main-app完全相同的IP地址 ✅
# sidecar可直接访问localhost:80
docker exec sidecar wget -qO- http://localhost:80 | head -3
# ... ✅ 共享网络命名空间
# 创建带DNS别名的网络
docker network create --driver bridge \
--subnet 172.21.0.0/16 \
app-network
# 运行容器并指定网络别名
docker run -d --name db-server \
--network app-network \
--network-alias mysql \
--network-alias database \
mysql:8.0
# 同网络容器可通过任一别名访问
docker run --rm --network app-network alpine:latest \
ping -c 1 mysql
# PING mysql (172.21.0.2) ✅
docker run --rm --network app-network alpine:latest \
ping -c 1 database
# PING database (172.21.0.2) ✅
# 列出所有网络
docker network ls
# NETWORK ID NAME DRIVER SCOPE
# a1b2c3d4 bridge bridge local
# e5f6g7h8 host host local
# i9j0k1l2 none null local
# m3n4o5p6 my-net bridge local
# 查看网络详情
docker network inspect my-net
# 连接运行中容器到另一网络
docker network connect app-network app-web
# app-web现在同时属于两个网络 ✅
# 断开网络
docker network disconnect app-network app-web
# 删除未使用的网络
docker network prune
# 删除指定网络
docker network rm my-net
# 创建前端和后端网络
docker network create frontend-net
docker network create backend-net
# 数据库——仅后端网络
docker run -d --name db \
--network backend-net \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.0-oracle
# API服务——同时属于两个网络
docker run -d --name api \
--network frontend-net \
nginx:alpine
docker network connect backend-net api
# Web前端——仅前端网络
docker run -d --name web \
--network frontend-net \
-p 8084:80 \
nginx:alpine
# 验证网络隔离
docker exec web ping -c 1 api
# PING api ✅ 前端可访问API
docker exec web ping -c 1 db
# ping: bad address 'db' ✅ 前端无法访问数据库
docker exec api ping -c 1 db
# PING db ✅ API可访问数据库
# 清理
docker rm -f web api db
docker network rm frontend-net backend-net
WARNING: IPv4 forwarding is disabled启用IP转发:
sysctl -w net.ipv4.ip_forward=1,并写入 /etc/sysctl.conf 持久化。
net-a 和 net-b,各放一个容器,验证跨网络不可通信-p 127.0.0.1:9999:80 启动Nginx,分别从本机和外部访问,观察差异iperf3,对比网络吞吐量