Docker 容器网络
什么是 Docker 网络
Docker 容器网络是 Docker 容器之间以及容器与外部世界之间进行通信的桥梁。当我们创建并运行容器时,Docker 会为每个容器分配一个独立的网络命名空间,使得容器拥有自己的网络协议栈、IP 地址、路由表和防火墙规则。
容器网络的工作原理
Docker 使用 Linux 命名空间(Namespace)技术实现网络隔离,每个容器都有自己独立的:
- 网络命名空间:容器拥有独立的网络协议栈
- 网卡:每容器至少有一对虚拟网卡(veth pair)
- IP 地址:容器获得独立的 IP 地址
- 端口:容器内部可以监听任意端口
- 路由表:独立的路由转发规则
- 防火墙规则:独立的 iptables 规则
容器网络的主要用途
- 容器间通信:让多个容器能够相互通信
- 服务暴露:将容器内的服务暴露给外部访问
- 网络隔离:不同项目或环境的容器网络相互隔离
- 负载均衡:配合 Ingress 实现流量分发
Docker 网络驱动
Docker 提供了多种网络驱动,每种驱动适用于不同的场景。
1. Bridge(桥接模式)
默认网络驱动,也是最常用的模式。
原理:Docker 会在宿主机上创建一个名为 docker0 的网桥,连接宿主机和容器。当容器启动时,Docker 会在宿主机和容器之间创建一对虚拟网卡(veth pair),一端连接到容器的 eth0,另一端连接到宿主机上的 docker0 网桥。
特点:
- 同一网络下的容器可以相互通信
- 容器与宿主机通过 NAT 转换通信
- 适合单主机容器通信场景
使用场景:本地开发环境、单服务器部署
示例:
# 创建桥接网络
docker network create --driver bridge my-bridge
# 运行容器并指定网络
docker run -d --name container1 --network my-bridge nginx
# 将已有容器连接到网络
docker network connect my-bridge container22. Host(主机模式)
容器直接使用宿主机的网络命名空间,不再进行网络隔离。
特点:
- 容器共享宿主机的 IP 地址和端口
- 性能最好,因为没有网络转发开销
- 容器端口直接暴露在宿主机上
使用场景:对网络性能要求高、需要使用宿主机全部网络资源的场景(如 Kubernetes 的网络插件)
示例:
# 使用主机网络模式
docker run -d --name container --network host nginx注意事项:
- 容器端口与宿主机端口冲突时会失败
- 容器之间无法通过网络隔离
3. Overlay(覆盖模式)
用于 Docker Swarm 集群中跨主机容器通信。
原理:在多台 Docker 主机上创建统一的虚拟网络,容器可以在不同宿主机之间透明通信。Overlay 网络使用 VXLAN 协议封装跨主机流量。
特点:
- 支持跨主机容器通信
- 自动服务发现(配合 Docker Swarm)
- 适合分布式部署
使用场景:Docker Swarm 集群、生产环境多主机部署
示例:
# 创建覆盖网络
docker network create --driver overlay my-overlay
# 在 Swarm 服务中使用
docker service create --name web --network my-overlay -p 80:80 nginx4. Macvlan
为容器分配真实的 MAC 地址,使容器像物理机一样出现在网络中。
原理:Docker 在物理网络接口上创建虚拟子接口(MACvlan),每个容器获得真实网络中的 IP 地址。
特点:
- 容器拥有真实 MAC 地址
- 容器可以直接访问物理网络
- 网络响应速度快(无需 NAT)
使用场景:需要容器直接接入物理网络的场景、遗留系统的容器化改造
示例:
# 创建 Macvlan 网络
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 my-macvlan
# 运行容器使用 Macvlan
docker run -d --name container --network my-macvlan nginx5. None(无网络)
容器创建后不配置任何网络,容器完全隔离。
特点:
- 容器没有网络接口(除 loopback 外)
- 容器完全与外部隔离
- 适用于不需要网络的场景
使用场景:离线计算、需完全隔离的安全任务
示例:
# 运行无网络容器
docker run -d --name container --network none nginx6. Network Plugins(网络插件)
Docker 支持第三方网络插件,实现更高级的网络功能。
常见插件:
- Calico:高性能三层网络插件,支持网络策略
- Flannel:简单易用的 Overlay 网络
- Weave:支持加密传输的 Overlay 网络
- Cilium:基于 eBPF 的网络和安全插件
容器网络常用命令
查看网络
# 列出所有网络
docker network ls
# 查看网络详细信息
docker network inspect bridge
# 查看容器网络连接信息
docker inspect container_name --format '{{json .NetworkSettings.Networks}}'创建网络
# 创建桥接网络
docker network create --driver bridge my-network
# 创建自定义子网和网关的桥接网络
docker network create --driver bridge \
--subnet=172.20.0.0/16 \
--gateway=172.20.0.1 \
my-custom-network
# 创建覆盖网络
docker network create --driver overlay my-overlay-network连接和断开网络
# 将容器连接到网络
docker network connect my-network container_name
# 将容器从网络断开
docker network disconnect my-network container_name删除网络
# 删除未使用的网络
docker network prune
# 删除指定网络
docker network rm my-network容器间通信
通过容器名通信
同在一个自定义网络中的容器,可以使用容器名直接进行通信:
# 创建网络
docker network create my-network
# 启动两个容器
docker run -d --name web --network my-network nginx
docker run -d --name api --network my-network alpine
# api 容器可以直接通过容器名访问 web
docker exec api ping web通过 Link(已废弃)
早期 Docker 提供 --link 参数实现容器间通信,现在已被自定义网络取代。
创建自定义网络的优势
- 自动 DNS 解析:同网络容器通过容器名互相发现
- 网络隔离:不同网络容器隔离
- 动态服务发现:容器可以随时加入或离开网络
容器与外部通信
端口映射
通过 -p 参数将容器端口映射到宿主机端口:
# 格式: -p 宿主机端口:容器端口
docker run -d -p 80:80 nginx # 宿主机 80 -> 容器 80
docker run -d -p 8080:80 nginx # 宿主机 8080 -> 容器 80
docker run -d -p 0.0.0.0:80:80 nginx # 指定监听地址查看端口映射
# 查看容器端口映射
docker port container_name
# 查看所有容器端口
docker ps --format "table {{.Names}}\t{{.Ports}}"随机端口映射
# 让 Docker 自动分配宿主机端口
docker run -d -P nginx # -P 映射所有 EXPOSE 端口网络隔离与安全
网络隔离策略
通过创建不同的网络实现隔离:
# 创建内部网络(无法访问外部)
docker network create --internal internal-network
# 不同网络的容器完全隔离
docker network create network-a
docker network create network-b容器防火墙规则
使用 iptables 控制容器网络访问:
# 禁止容器访问外部网络(需要修改 iptables)
iptables -I DOCKER -s <container_ip> -j DROP
# 查看 Docker 相关的 iptables 规则
iptables -L -n | grep DOCKER常见问题排查
容器无法访问外网
# 检查宿主机网络和 Docker 网桥
ip addr show docker0
# 检查 iptables 规则
iptables -L -n | grep DOCKER
# 重启 Docker 服务
sudo systemctl restart docker
# 检查 DNS 配置
docker run --rm busybox cat /etc/resolv.conf容器间无法通信
# 检查容器所在网络
docker inspect container_name --format '{{json .NetworkSettings.Networks}}'
# 检查网络是否存在
docker network ls
# 检查网络连接状态
docker network inspect network_name
# 重新连接容器
docker network disconnect network_name container_name
docker network connect network_name container_name端口映射失败
# 检查端口是否被占用
lsof -i :80
netstat -tulpn | grep :80
# 检查是否有服务在监听
docker ps -a
# 查看 Docker 日志
journalctl -u docker -f最佳实践
- 使用自定义网络:优先使用自定义桥接网络而不是默认网络
- 合理的网络规划:生产环境做好网络分段规划
- 最小权限原则:只开放必要的端口和访问权限
- 使用网络插件:大规模集群使用 Calico、Cilium 等专业插件
- 监控网络指标:关注网络流量、连接数等关键指标
- 定期清理无用网络:避免网络资源泄漏
CodeVortex