Skip to content

Docker 容器网络

什么是 Docker 网络

Docker 容器网络是 Docker 容器之间以及容器与外部世界之间进行通信的桥梁。当我们创建并运行容器时,Docker 会为每个容器分配一个独立的网络命名空间,使得容器拥有自己的网络协议栈、IP 地址、路由表和防火墙规则。

容器网络的工作原理

Docker 使用 Linux 命名空间(Namespace)技术实现网络隔离,每个容器都有自己独立的:

  • 网络命名空间:容器拥有独立的网络协议栈
  • 网卡:每容器至少有一对虚拟网卡(veth pair)
  • IP 地址:容器获得独立的 IP 地址
  • 端口:容器内部可以监听任意端口
  • 路由表:独立的路由转发规则
  • 防火墙规则:独立的 iptables 规则

容器网络的主要用途

  1. 容器间通信:让多个容器能够相互通信
  2. 服务暴露:将容器内的服务暴露给外部访问
  3. 网络隔离:不同项目或环境的容器网络相互隔离
  4. 负载均衡:配合 Ingress 实现流量分发

Docker 网络驱动

Docker 提供了多种网络驱动,每种驱动适用于不同的场景。

1. Bridge(桥接模式)

默认网络驱动,也是最常用的模式。

原理:Docker 会在宿主机上创建一个名为 docker0 的网桥,连接宿主机和容器。当容器启动时,Docker 会在宿主机和容器之间创建一对虚拟网卡(veth pair),一端连接到容器的 eth0,另一端连接到宿主机上的 docker0 网桥。

特点

  • 同一网络下的容器可以相互通信
  • 容器与宿主机通过 NAT 转换通信
  • 适合单主机容器通信场景

使用场景:本地开发环境、单服务器部署

示例

bash
# 创建桥接网络
docker network create --driver bridge my-bridge

# 运行容器并指定网络
docker run -d --name container1 --network my-bridge nginx

# 将已有容器连接到网络
docker network connect my-bridge container2

2. Host(主机模式)

容器直接使用宿主机的网络命名空间,不再进行网络隔离。

特点

  • 容器共享宿主机的 IP 地址和端口
  • 性能最好,因为没有网络转发开销
  • 容器端口直接暴露在宿主机上

使用场景:对网络性能要求高、需要使用宿主机全部网络资源的场景(如 Kubernetes 的网络插件)

示例

bash
# 使用主机网络模式
docker run -d --name container --network host nginx

注意事项

  • 容器端口与宿主机端口冲突时会失败
  • 容器之间无法通过网络隔离

3. Overlay(覆盖模式)

用于 Docker Swarm 集群中跨主机容器通信。

原理:在多台 Docker 主机上创建统一的虚拟网络,容器可以在不同宿主机之间透明通信。Overlay 网络使用 VXLAN 协议封装跨主机流量。

特点

  • 支持跨主机容器通信
  • 自动服务发现(配合 Docker Swarm)
  • 适合分布式部署

使用场景:Docker Swarm 集群、生产环境多主机部署

示例

bash
# 创建覆盖网络
docker network create --driver overlay my-overlay

# 在 Swarm 服务中使用
docker service create --name web --network my-overlay -p 80:80 nginx

4. Macvlan

为容器分配真实的 MAC 地址,使容器像物理机一样出现在网络中。

原理:Docker 在物理网络接口上创建虚拟子接口(MACvlan),每个容器获得真实网络中的 IP 地址。

特点

  • 容器拥有真实 MAC 地址
  • 容器可以直接访问物理网络
  • 网络响应速度快(无需 NAT)

使用场景:需要容器直接接入物理网络的场景、遗留系统的容器化改造

示例

bash
# 创建 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 nginx

5. None(无网络)

容器创建后不配置任何网络,容器完全隔离。

特点

  • 容器没有网络接口(除 loopback 外)
  • 容器完全与外部隔离
  • 适用于不需要网络的场景

使用场景:离线计算、需完全隔离的安全任务

示例

bash
# 运行无网络容器
docker run -d --name container --network none nginx

6. Network Plugins(网络插件)

Docker 支持第三方网络插件,实现更高级的网络功能。

常见插件

  • Calico:高性能三层网络插件,支持网络策略
  • Flannel:简单易用的 Overlay 网络
  • Weave:支持加密传输的 Overlay 网络
  • Cilium:基于 eBPF 的网络和安全插件

容器网络常用命令

查看网络

bash
# 列出所有网络
docker network ls

# 查看网络详细信息
docker network inspect bridge

# 查看容器网络连接信息
docker inspect container_name --format '{{json .NetworkSettings.Networks}}'

创建网络

bash
# 创建桥接网络
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

连接和断开网络

bash
# 将容器连接到网络
docker network connect my-network container_name

# 将容器从网络断开
docker network disconnect my-network container_name

删除网络

bash
# 删除未使用的网络
docker network prune

# 删除指定网络
docker network rm my-network

容器间通信

通过容器名通信

同在一个自定义网络中的容器,可以使用容器名直接进行通信:

bash
# 创建网络
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

早期 Docker 提供 --link 参数实现容器间通信,现在已被自定义网络取代。

创建自定义网络的优势

  1. 自动 DNS 解析:同网络容器通过容器名互相发现
  2. 网络隔离:不同网络容器隔离
  3. 动态服务发现:容器可以随时加入或离开网络

容器与外部通信

端口映射

通过 -p 参数将容器端口映射到宿主机端口:

bash
# 格式: -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  # 指定监听地址

查看端口映射

bash
# 查看容器端口映射
docker port container_name

# 查看所有容器端口
docker ps --format "table {{.Names}}\t{{.Ports}}"

随机端口映射

bash
# 让 Docker 自动分配宿主机端口
docker run -d -P nginx  # -P 映射所有 EXPOSE 端口

网络隔离与安全

网络隔离策略

通过创建不同的网络实现隔离:

bash
# 创建内部网络(无法访问外部)
docker network create --internal internal-network

# 不同网络的容器完全隔离
docker network create network-a
docker network create network-b

容器防火墙规则

使用 iptables 控制容器网络访问:

bash
# 禁止容器访问外部网络(需要修改 iptables)
iptables -I DOCKER -s <container_ip> -j DROP

# 查看 Docker 相关的 iptables 规则
iptables -L -n | grep DOCKER

常见问题排查

容器无法访问外网

bash
# 检查宿主机网络和 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

容器间无法通信

bash
# 检查容器所在网络
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

端口映射失败

bash
# 检查端口是否被占用
lsof -i :80
netstat -tulpn | grep :80

# 检查是否有服务在监听
docker ps -a

# 查看 Docker 日志
journalctl -u docker -f

最佳实践

  1. 使用自定义网络:优先使用自定义桥接网络而不是默认网络
  2. 合理的网络规划:生产环境做好网络分段规划
  3. 最小权限原则:只开放必要的端口和访问权限
  4. 使用网络插件:大规模集群使用 Calico、Cilium 等专业插件
  5. 监控网络指标:关注网络流量、连接数等关键指标
  6. 定期清理无用网络:避免网络资源泄漏

Released under the MIT License.