Docker——4.Docker容器网络
容器网络概述
Docker 容器在运行时,需要与宿主机、其他容器以及外部网络进行通信。Docker 通过 网络驱动(Network Driver) 机制为容器提供灵活的网络配置能力。每个容器在创建时都会被分配一个网络命名空间(Network Namespace),从而实现网络层面的隔离。
Docker 的网络架构核心组件包括:
- Network Namespace:为每个容器提供独立的网络栈(网卡、路由表、iptables 规则等)。
- Veth Pair:虚拟以太网设备对,用于连接容器与宿主机网桥(如
docker0)。 - Linux Bridge:虚拟交换机(如
docker0),负责同一宿主机内容器间的二层转发。 - NAT / iptables:实现容器访问外网及端口映射(
-p参数)。
容器网络种类
Docker 支持多种网络模式,适用于不同的使用场景:
| 网络模式 | 驱动(Driver) | 说明 | 典型场景 |
|---|---|---|---|
| Bridge(桥接) | bridge | Docker 默认网络模式。容器通过虚拟网桥 docker0 互联,经 NAT 访问外网。每个容器拥有独立 IP(默认 172.17.0.0/16)。 | 单机多容器通信、开发测试环境 |
| Host(主机) | host | 容器与宿主机共享网络命名空间,无独立网卡和 IP,直接使用宿主机网络栈。性能最高,但存在端口冲突风险。 | 对网络性能要求极高、无需网络隔离的服务(如监控 Agent) |
| Container(容器复用) | container | 新容器与指定容器共享网络栈(IP、端口),但文件系统和进程仍然隔离。类似 Pod 中多容器共享网络的概念。 | Sidecar 模式、网络调试 |
| None(无网络) | null | 容器仅拥有 lo 回环网卡,无任何外部网络连接。完全隔离。 | 安全沙箱、纯计算任务、离线处理 |
| Overlay(覆盖网络) | overlay | 基于 VXLAN 等隧道技术,实现跨 Docker Host 的容器通信。Docker Swarm 默认使用此模式。 | 多节点集群、Swarm 编排 |
| Macvlan | macvlan | 为容器分配独立的 MAC 地址,使其表现为物理网络中的独立主机,可直接被外部网络访问。 | 需要容器直接接入物理网络、传统应用迁移 |
| 自定义网络(User-defined) | bridge / overlay | 用户通过 docker network create 创建,支持自定义网段、DNS 服务发现、网络隔离等高级特性。 | 生产环境多项目隔离、微服务架构 |
补充说明:
- 单机环境下,Bridge 是最常用的模式;跨主机通信通常需要借助 Overlay、Flannel、Calico 等方案。
- Flannel 并非 Docker 原生驱动,而是通过为每台宿主机分配不冲突的子网,配合 Docker Bridge 实现跨主机容器通信,属于第三方 Overlay 方案。
- 自定义 Bridge 网络相比默认
docker0,额外提供了容器名 DNS 解析和自动网络隔离能力,推荐在生产环境中使用。
一、Docker 本地网络模式实验
Docker 默认提供了几种网络模式,用于处理容器与宿主机、容器与外网的连接。
1. Bridge 模式(桥接模式)
这是 Docker 的默认网络模式。所有容器连接到 docker0 网桥,通过 NAT 访问外网。
- 特点:
- 默认网段:
172.17.0.0/16。 - 不同 Docker Host 上的容器默认无法直接通信(因为网段冲突)。
实验步骤:
- 查看默认网桥信息
# 查看宿主机网卡信息,确认 docker0 存在
[root@wen ~]# ip a
# 输出中应包含 docker0,状态通常为 DOWN,IP 为 172.17.0.1/16
- 查看 Docker 网络列表
[root@wen ~]# docker network ls
# 输出示例:
# NETWORK ID NAME DRIVER SCOPE
# f2f19a5e2ebc bridge bridge local
# 5aeb2630e0f9 host host local
# 44b9cab07f8c none null local
- 启动 Bridge 模式容器
# 默认即为 --network bridge,可省略
[root@wen ~]# docker run -it --network bridge centos:7.7.1908 /bin/bash
# 进入容器后查看 IP
[root@b76b36b8c644 /]# ifconfig
# 输出示例:inet 172.17.0.2 (属于 172.17.0.0/16 网段)
- 查看网络详情
[root@wen ~]# docker network inspect bridge
2. Host 模式(主机模式)
容器与宿主机共享网络命名空间,没有独立的网卡和 IP。
- 特点:
- 容器与宿主机 IP、主机名完全一致。
- 缺点:多个容器若绑定相同端口(如 80),会产生端口冲突。
实验步骤:
- 启动两个 Host 模式容器
# 启动容器 C1
[root@wen ~]# docker run -it --network host --name C1 centos:7.7.1908 /bin/bash
[root@wen /]# yum -y install iproute
[root@wen /]# ip a # 看到的即为宿主机网络
# 启动容器 C2 (在另一个终端)
[root@wen ~]# docker run -it --network host --name C2 centos:7.7.1908 /bin/bash
- 验证端口冲突
# 在 C1 中安装并启动 httpd
[root@wen /]# yum -y install httpd
[root@wen /]# echo "test httpd" > /var/www/html/index.html
[root@wen /]# httpd -k start # 启动成功
# 在 C2 中执行相同操作
[root@wen /]# yum -y install httpd
[root@wen /]# httpd -k start
# 报错信息:(98)Address already in use: AH00072: make_sock: could not bind to address [::]:80
# 说明端口被 C1 占用
3. Container 模式(容器复用模式)
新容器不创建独立网卡,而是与指定容器共享网络栈。
实验步骤:
# 1. 启动第一个容器 d1
[root@wen ~]# docker run -it --name d1 centos:7.7.1908 /bin/bash
# 2. 启动 d2,指定共享 d1 的网络
[root@wen ~]# docker run -it --name d2 --network container:d1 centos:7.7.1908 /bin/bash
# 结果:d1 和 d2 拥有相同的 IP 地址和端口范围,但文件系统和进程隔离。
4. None 模式(无网络模式)
容器仅有 lo 回环网卡,无外部网络连接。
实验步骤:
# 启动容器
[root@wen ~]# docker run -it --network none centos:7.7.1908 /bin/bash
# 容器内尝试安装软件或查看 IP 会失败/无 IP
[root@0fd5a2fbc44c /]# yum -y install iproute # 可能因无网报错
[root@wen ~]# docker inspect 0fd5a2fbc44c # 查看详细信息确认无 IP
二、跨 Docker Host 容器间通信实验 (Flannel)
为了解决不同宿主机上容器网段冲突及通信问题,使用 Flannel + Etcd 构建 Overlay 网络。
- 环境规划:
- Node1:
192.168.2.124(安装 etcd, flannel, docker) - Node2:
192.168.2.125(安装 flannel, docker) - 容器网段:
172.200.0.0/16
1. 环境准备 (Node1 & Node2)
1.1 关闭防火墙和 SELinux
# 两台机器都执行
[root@localhost ~]# systemctl stop firewalld.service
[root@localhost ~]# systemctl disable firewalld.service
[root@localhost ~]# setenforce 0 # 临时关闭
# 永久关闭需修改 /etc/selinux/config
1.2 修改主机名
# Node1 (192.168.2.124) 执行
[root@node1 ~]# hostnamectl set-hostname node1
# Node2 (192.168.2.125) 执行
[root@node2 ~]# hostnamectl set-hostname node2
1.3 配置 Hosts 解析
# 两台机器都执行
[root@node1 ~]# cat >> /etc/hosts <<EOF
192.168.2.124 node1
192.168.2.124 etcd
192.168.2.125 node2
EOF
1.4 安装软件
# Node1 安装 etcd, flannel, docker
[root@node1 ~]# yum -y install etcd flannel docker
# Node2 安装 flannel, docker
[root@node2 ~]# yum -y install flannel docker
2. 配置 Etcd (仅 Node1)
2.1 修改 Etcd 配置
[root@node1 ~]# vim /etc/etcd/etcd.conf
# 修改第6行:监听所有地址
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
# 修改第21行:广播地址
ETCD_ADVERTISE_CLIENT_URLS="http://etcd:2379,http://etcd:4001"
2.2 启动 Etcd 并验证
[root@node1 ~]# systemctl start etcd
[root@node1 ~]# systemctl enable etcd
# 验证健康状态
[root@node1 ~]# etcdctl cluster-health
# 输出应显示 cluster is healthy
3. 配置 Flannel (Node1 & Node2)
3.1 配置 Flannel 连接 Etcd (两台机器)
[root@node1 ~]# vim /etc/sysconfig/flanneld
# 修改第4行,指向 etcd 地址
FLANNEL_ETCD_ENDPOINTS="http://etcd:2379"
# 前缀保持默认
FLANNEL_ETCD_PREFIX="/atomic.io/network"
3.2 在 Etcd 中配置容器网段 (仅 Node1)
# 写入网络配置
[root@node1 ~]# etcdctl mk /atomic.io/network/config '{ "Network": "172.200.0.0/16" }'
# 验证写入
[root@node1 ~]# etcdctl get /atomic.io/network/config
# 输出:{ "Network": "172.200.0.0/16" }
4. 启动 Flannel 并关联 Docker (Node1 & Node2)
4.1 启动 Flannel 服务
# 两台机器都执行
[root@node ~]# systemctl start flanneld
[root@node ~]# systemctl enable flanneld
# 查看是否生成 flannel0 网卡
[root@node ~]# ip a
# 应看到 flannel0 接口
4.2 配置 Docker 使用 Flannel 网段
原理:Flannel 启动后会生成 /run/flannel/subnet.env,Docker 需要读取其中的 bip 和 mtu。
Node1 操作:
# 1. 查看分配的子网信息
[root@node1 ~]# cat /run/flannel/subnet.env
# 假设输出 FLANNEL_SUBNET=172.200.27.1/24, FLANNEL_MTU=1472
# 2. 修改 Docker 配置
[root@node1 ~]# vim /etc/docker/daemon.json
{
"insecure-registries": ["http://192.168.2.124"],
"bip": "172.200.27.1/24", # 对应 subnet.env 中的 FLANNEL_SUBNET
"mtu": 1472 # 对应 subnet.env 中的 FLANNEL_MTU
}
# 3. 重启 Docker
[root@node1 ~]# systemctl restart docker
# 4. 验证 docker0 IP 是否变化
[root@node1 ~]# ip a
# docker0 的 inet 应变为 172.200.27.1/24
Node2 操作:
# 1. 查看分配的子网信息 (Node2 会分配到不同子网)
[root@node2 ~]# cat /run/flannel/subnet.env
# 假设输出 FLANNEL_SUBNET=172.200.21.1/24
# 2. 修改 Docker 配置
[root@node2 ~]# vim /etc/docker/daemon.json
{
"insecure-registries": ["http://192.168.2.125"],
"bip": "172.200.21.1/24", # 注意这里是 Node2 分配到的子网
"mtu": 1472
}
# 3. 重启 Docker
[root@node2 ~]# systemctl restart docker
5. 最终验证
Node1 启动容器
[root@node1 ~]# docker run -it centos:7.7.1908 /bin/bash
[root@... /]# ip a
# 容器 IP 应为 172.200.27.x
Node2 启动容器
[root@node2 ~]# docker run -it centos:7.7.1908 /bin/bash
[root@... /]# ip a
# 容器 IP 应为 172.200.21.x
通信测试在 Node1 的容器中 ping Node2 容器的 IP(例如 ping 172.200.21.2),若能通,则跨主机通信配置成功。
注意
如果相互ping不通,可能是没有打开ipv4转发
# (Node1 & Node2 均需执行)
# 1. 使用 echo 命令将配置永久写入 /etc/sysctl.conf
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# 2. 执行命令,让配置立即生效
sysctl -p
更多推荐

所有评论(0)