Docker 网络模式详解:bridge、host、overlay 和 macvlan

Docker 网络模式详解:bridge、host、overlay 和 macvlan

Docker 提供了多种网络模式,让容器既能灵活通信,又能实现安全隔离。无论是单机多容器应用,还是跨主机的 Swarm 集群,亦或需要直接接入物理网络的 IoT 设备,Docker 的网络子系统都有对应的解决方案。本文将系统讲解 Docker 全部 5 种网络模式------bridge、host、none、overlay 和 macvlan------并提供完整的配置示例和实战演示,帮助你在生产环境中做出正确的网络架构决策。


服务器配置

学习和测试 Docker 网络不需要顶级硬件,但需要一台干净、稳定的 Linux 环境。推荐选用 雨云服务器 rainyun+com2 核 4GB 机型 ,该配置足以同时运行多个容器、测试 Swarm 单节点集群,以及模拟 macvlan 和 overlay 网络场景。注册填码 2026off 领 5 折券,性价比极高。

推荐操作系统:Ubuntu 22.04 LTS 或 Debian 12。本文所有命令均在该环境下验证通过。


核心概念

Docker 网络模式本质上是通过 Linux 内核的网络命名空间(network namespace)、虚拟网卡(veth pair)、网桥(bridge)以及 iptables/nftables 规则来实现的。理解这一底层机制有助于排查网络故障。

网络模式 隔离性 跨主机 典型场景
bridge 单机多容器,默认推荐
host 高性能、低延迟应用
none 完全 安全沙盒、纯计算任务
overlay Swarm 集群、微服务
macvlan 否* IoT、需要独立 IP 的场景

安装与配置

安装 Docker

bash 复制代码
# 一键安装脚本(Ubuntu/Debian)
curl -fsSL https://get.docker.com | bash

# 将当前用户加入 docker 组,避免每次都用 sudo
sudo usermod -aG docker $USER
newgrp docker

# 验证安装
docker version
docker info

模式一:bridge(默认网络模式)

bridge 是 Docker 的默认网络模式。每个容器拥有独立的网络命名空间,通过虚拟网卡对连接到宿主机上的 docker0 网桥,再经 NAT 访问外网。

使用默认 bridge 网络
bash 复制代码
# 运行两个容器,均连接默认 bridge
docker run -d --name app1 --network bridge nginx:alpine
docker run -d --name app2 --network bridge alpine sleep 3600

# 查看默认 bridge 网络信息
docker network inspect bridge

# 默认 bridge 网络中容器只能通过 IP 互访(不支持 DNS 解析容器名)
docker exec app2 ping $(docker inspect -f '{{.NetworkSettings.IPAddress}}' app1)
端口映射(-p 参数)
bash 复制代码
# 将容器 80 端口映射到宿主机 8080
docker run -d --name web -p 8080:80 nginx:alpine

# 映射到指定 IP
docker run -d --name web2 -p 127.0.0.1:8081:80 nginx:alpine

# 查看端口映射
docker port web
用户自定义 bridge 网络(推荐生产使用)

自定义 bridge 网络相比默认 bridge 有两大优势:容器名 DNS 解析更好的隔离性

bash 复制代码
# 创建自定义 bridge 网络
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --gateway 172.20.0.1 \
  myapp-network

# 运行容器并连接到自定义网络
docker run -d --name frontend --network myapp-network nginx:alpine
docker run -d --name backend  --network myapp-network python:3.11-alpine python3 -m http.server 8000

# 自定义网络支持容器名 DNS 解析------直接 ping 容器名即可
docker exec frontend ping backend
docker exec frontend wget -qO- http://backend:8000

# 将已运行的容器动态连接/断开网络
docker network connect myapp-network some-existing-container
docker network disconnect myapp-network some-existing-container
查看网络详情
bash 复制代码
docker network ls
docker network inspect myapp-network
# 查看容器的网络配置
docker inspect --format='{{json .NetworkSettings.Networks}}' frontend | python3 -m json.tool

模式二:host

host 模式下,容器直接共享宿主机的网络命名空间,没有网络隔离。容器中的服务监听的端口直接绑定在宿主机的网络接口上,无需端口映射,延迟极低。

bash 复制代码
# 使用 host 网络运行容器
docker run -d --name nginx-host --network host nginx:alpine

# 此时 nginx 直接监听宿主机的 80 端口
curl http://localhost:80

# host 模式下 -p 参数无效(直接用宿主机端口)
# 验证:容器内看到的网络接口与宿主机完全一致
docker exec nginx-host ip addr show

适用场景:

  • 需要最低网络延迟的应用(如高性能代理、游戏服务器)
  • 需要监听宿主机特定物理网卡的服务
  • 网络性能测试工具

限制:

  • 端口冲突:若宿主机已占用某端口,容器无法再监听该端口
  • 安全隔离性弱,不推荐在多租户环境使用
  • macOS 和 Windows 上的 Docker Desktop 不支持 host 模式

模式三:none

none 模式为容器创建独立的网络命名空间,但不配置任何网络接口(除了 loopback)。容器完全与外部网络隔离。

bash 复制代码
# 运行完全无网络的容器
docker run -d --name isolated --network none alpine sleep 3600

# 验证:容器内只有 lo 接口
docker exec isolated ip addr show
# 输出只有 127.0.0.1/8

# 无法访问外网
docker exec isolated ping 8.8.8.8
# ping: bad address '8.8.8.8'

适用场景:

  • 安全沙盒:运行不可信代码
  • 纯 CPU 密集型计算任务(如编译、数据处理)
  • 需要通过 volume 进行数据交换而不需要网络的任务

模式四:overlay

overlay 网络专为 Docker Swarm 多主机集群设计,能让不同宿主机上的容器像在同一个局域网内通信,无需手动配置路由。

bash 复制代码
# 首先初始化 Swarm(单节点也可测试)
docker swarm init --advertise-addr $(hostname -I | awk '{print $1}')

# 创建 overlay 网络
docker network create \
  --driver overlay \
  --subnet 10.0.9.0/24 \
  myswarm-network

# 在 Swarm 中创建服务,使用 overlay 网络
docker service create \
  --name web-service \
  --network myswarm-network \
  --replicas 3 \
  -p 8080:80 \
  nginx:alpine

# 查看服务状态
docker service ls
docker service ps web-service

# 创建 attachable overlay 网络(允许独立容器连接,便于调试)
docker network create \
  --driver overlay \
  --attachable \
  --subnet 10.0.10.0/24 \
  debug-overlay

# 在 attachable overlay 网络上运行独立容器
docker run -d --name debugger --network debug-overlay alpine sleep 3600

多主机集群加入:

bash 复制代码
# 在管理节点获取 worker 加入令牌
docker swarm join-token worker

# 在 Worker 节点执行(替换实际 token 和 IP)
docker swarm join --token SWMTKN-1-xxxxx 192.168.1.100:2377

模式五:macvlan

macvlan 允许容器拥有独立的 MAC 地址和 IP 地址,直接接入物理网络,就像一台独立的物理机。这是 IoT、裸机服务以及需要固定 IP 的场景的最佳选择。

bash 复制代码
# 查看宿主机物理网卡名称
ip link show
# 假设物理网卡为 eth0,子网为 192.168.1.0/24,网关为 192.168.1.1

# 创建 macvlan 网络
docker network create \
  --driver macvlan \
  --subnet 192.168.1.0/24 \
  --gateway 192.168.1.1 \
  --opt parent=eth0 \
  macvlan-net

# 运行容器,分配固定 IP
docker run -d \
  --name iot-device \
  --network macvlan-net \
  --ip 192.168.1.150 \
  alpine sleep 3600

# 验证容器获得了独立 IP(可从局域网其他设备直接访问)
docker exec iot-device ip addr show
docker exec iot-device ip route show

# 宿主机访问 macvlan 容器需要创建 macvlan 子接口
ip link add macvlan-shim link eth0 type macvlan mode bridge
ip addr add 192.168.1.151/32 dev macvlan-shim
ip link set macvlan-shim up
ip route add 192.168.1.150/32 dev macvlan-shim

注意: 宿主机物理网卡需要开启混杂模式(或交换机端口允许多 MAC 地址)才能正常工作:

bash 复制代码
ip link set eth0 promisc on

Docker Compose 中的网络配置

基础网络配置

yaml 复制代码
# docker-compose.yml
version: "3.9"

services:
  frontend:
    image: nginx:alpine
    ports:
      - "80:80"
    networks:
      - frontend-net

  backend:
    image: python:3.11-alpine
    command: python3 -m http.server 8000
    networks:
      - frontend-net
      - backend-net

  database:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: secret
    networks:
      - backend-net  # 只在后端网络,前端无法直接访问

networks:
  frontend-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.21.0.0/24

  backend-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.22.0.0/24

使用外部已有网络

yaml 复制代码
networks:
  shared-network:
    external: true   # 使用已存在的网络,不由 Compose 创建/销毁
    name: myapp-network

host 和 none 模式的 Compose 配置

yaml 复制代码
services:
  high-perf-proxy:
    image: haproxy:latest
    network_mode: host   # 使用 host 网络

  sandbox-job:
    image: python:3.11
    network_mode: none   # 完全无网络
    command: python3 /scripts/compute.py

实战演示

多容器应用的网络隔离最佳实践

以下是一个典型的三层应用(前端、后端 API、数据库)的网络隔离方案:

yaml 复制代码
# docker-compose.prod.yml
version: "3.9"

services:
  nginx:
    image: nginx:alpine
    ports:
      - "443:443"
      - "80:80"
    networks:
      - public-net
    depends_on:
      - api

  api:
    image: myapp-api:latest
    networks:
      - public-net    # 接收来自 nginx 的流量
      - private-net   # 访问数据库
    environment:
      DB_HOST: postgres  # 通过容器名 DNS 解析
      REDIS_HOST: redis

  postgres:
    image: postgres:16-alpine
    networks:
      - private-net  # 仅在私有网络,外部无法直接访问
    volumes:
      - pg-data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    networks:
      - private-net

networks:
  public-net:
    driver: bridge
  private-net:
    driver: bridge
    internal: true  # 禁止访问外网,纯内部通信网络

volumes:
  pg-data:

网络排查:常用命令速查

bash 复制代码
# ===== 查看网络 =====
docker network ls                          # 列出所有网络
docker network inspect <network-name>     # 查看网络详情(含所有容器 IP)
docker inspect <container> | grep -A 20 "Networks"  # 查看容器网络配置

# ===== 连通性测试 =====
docker exec <container> ping <target-ip>           # ping 测试
docker exec <container> ping <container-name>      # DNS 解析 + ping
docker exec <container> wget -qO- http://<host>:<port>  # HTTP 连通测试
docker exec <container> nc -zv <host> <port>       # TCP 端口测试

# ===== 网络状态 =====
docker exec <container> ip addr show               # 查看网卡和 IP
docker exec <container> ip route show              # 查看路由表
docker exec <container> ss -tlnp                   # 查看监听端口(替代 netstat)
docker exec <container> cat /etc/resolv.conf       # 查看 DNS 配置

# ===== 宿主机侧排查 =====
ip link show                     # 查看所有网络接口(含 docker0、veth 等)
bridge link show                 # 查看 bridge 上连接的 veth 接口
iptables -t nat -L -n -v         # 查看 Docker 配置的 NAT 规则
iptables -L DOCKER -n -v         # 查看 Docker 防火墙规则

# ===== 清理 =====
docker network prune             # 删除所有未使用的网络
docker network rm <network-name> # 删除指定网络

常见问题与解决

Q:自定义 bridge 网络的容器为何无法解析容器名?

确认容器是否连接到了同一个 自定义网络(不是默认的 bridge)。默认 bridge 网络不支持容器名 DNS,只有用户自定义网络才支持。

Q:macvlan 容器无法与宿主机通信?

这是 macvlan 的内核限制。解决方法是在宿主机上创建 macvlan 子接口(见上文配置),通过该接口与容器通信。

Q:overlay 网络创建报错"This node is not a swarm manager"?

需要先执行 docker swarm init 初始化 Swarm,overlay 网络依赖 Swarm 的 key-value 存储。


Docker 网络模式各有适用场景:日常开发用自定义 bridge,高性能场景考虑 host,安全隔离用 none,集群部署选 overlay,物理网络集成用 macvlan。掌握这 5 种模式,能让你的容器化架构更加灵活和安全。如果你还没有合适的服务器环境来练习,推荐注册 雨云服务器 rainyun+com ,选择 2 核 4GB 机型 ,注册填码 2026off 领 5 折券,立即开始你的 Docker 网络实战之旅。

相关推荐
有个人神神叨叨2 小时前
[特殊字符] 东芝天氟地水 + 宏云智能 → 米家/HA 统一控制,智能家居整合方案 - 手残党求骂醒版
网络·智能家居
AI科技星3 小时前
全域粒子质量几何曲率统一公式体系(通俗易懂版)
c语言·开发语言·网络·量子计算·agi
minji...3 小时前
Linux 网络基础之传输层协议TCP(九)从内核源码的角度打通系统与网络之间的关系,套接字多态的体现
linux·运维·服务器·网络·网络协议·tcp/ip·http
yyuuuzz3 小时前
独立开发者线上服务运维的几点实践经验
运维·服务器·网络·云计算·aws
想唱rap3 小时前
IO多路转接Select
运维·服务器·网络·数据库·sql·tcp/ip·mysql
沪漂阿龙3 小时前
Docker 面试题详解:容器、镜像、Dockerfile、网络、Volume、Compose、安全与生产实践一次讲透
网络·安全·docker
灰子学技术3 小时前
Envoy IP 标签(IP Tagging)功能实现分析
网络·网络协议·tcp/ip
小夏子_riotous3 小时前
Kubernetes学习路径——7. Pod控制器详解
docker·云原生·容器·kubernetes·云计算·paas·kubelet
楼兰公子3 小时前
《深入理解Linux网络技术内幕》全套学习资料合集
linux·网络·应用·驱动