Docker 单机网络:从 None 到 Custom

为什么需要关心 Docker 网络?

在容器化的世界里,Docker 无疑是明星级的技术。当我们在一台主机上运行多个容器时,如何让它们之间以及它们与外部世界进行通信,就成了核心问题之一。今天,我们就来深入探讨 Docker 在单台宿主机上的几种核心网络模式,并通过实例来理解它们的差异和适用场景。
容器本质上是隔离的进程环境。网络隔离是其中重要的一环。Docker 提供了不同的网络模式,让我们可以根据应用需求,在隔离性性能易用性之间做出选择。理解这些模式对于构建健壮、高效的容器化应用至关重要。

Docker 的五种单机网络驱动

Docker 默认提供了几种网络驱动(Driver),用于创建不同类型的单机网络。我们可以通过 docker network ls 命令查看当前宿主机上存在的网络:

root@docker102:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
870e105321fc   bridge    bridge    local  # 默认桥接网络
d97f63ed6d57   host      host      local  # Host 网络
2646275ea427   none      null      local  # None 网络
# ... 可能还有其他自定义网络

这里的 DRIVER 列就指明了网络的类型。SCOPElocal 表示这些网络仅限于当前 Docker 主机。

下面我们逐一解析这几种常见的单机网络类型:

1. none 网络 (--network none)

  • 特点:最简单的模式。选择此模式的容器,将不会配置任何网络接口(除了一个 lo 本地回环接口)。它与宿主机、其他容器完全隔离。
  • 原理:容器拥有自己的网络命名空间,但 Docker 不为其进行任何网络配置。
  • 适用场景
    • 对网络安全性要求极高,不需要联网的容器(例如,执行一次性密码生成、数据处理任务的批处理作业)。
    • 需要进行高度自定义网络配置的场景,用户可以手动接管容器的网络设置。
  • 示例
    # 启动一个使用 none 网络的容器 c1-none
    docker run -d --name c1-none --network none registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
    
    # 查看 c1-none 的网络接口,只有 lo
    docker exec c1-none ip addr show
    # 或者使用 ifconfig (如果镜像包含该命令)
    # docker exec c1-none ifconfig -a
    
    你会看到输出只有 lo 接口,地址是 127.0.0.1

2. bridge 网络 (--network bridge 或 默认)

  • 特点:这是 Docker 默认的网络模式。当你运行容器时不指定 --network 参数,通常使用的就是这个模式。Docker 会创建一个名为 docker0 的虚拟网桥(在较新版本中可能是随机名称的网桥,但概念相同),并为每个连接到该网络的容器分配一个独立的网络命名空间和 IP 地址。
  • 原理
    1. Docker Daemon 启动时(或首次使用 bridge 网络时)在宿主机上创建一个 Linux 网桥 (docker0)。
    2. 为每个连接到此网络的容器创建一个独立的网络命名空间。
    3. 在容器内创建一对虚拟以太网设备(veth pair),一端(如 eth0)留在容器的网络命名空间内,另一端连接到宿主机的 docker0 网桥上。
    4. Docker 从 docker0 网桥的子网(默认为 172.17.0.0/16)中为容器的 eth0 分配 IP 地址。
    5. docker0 网桥充当这些容器的网关,并通过宿主机的 iptables 规则实现容器与外部网络的通信(NAT)。
  • 优点:提供了良好的网络隔离。同一 bridge 网络下的容器可以通过 IP 地址互相访问。
  • 缺点
    • 默认 bridge 网络下的容器之间不能通过容器名称直接访问(需要使用 --link 选项,但已不推荐,或使用 IP)。
    • 性能相比 host 网络有损耗(因为数据包需要经过网桥和 NAT)。
    • 端口映射需要显式使用 -p-P 参数(例如 -p 8080:80)。
  • 示例
    # 启动 c2-bridge,明确指定 bridge 网络
    docker run -d --name c2-bridge --network bridge registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
    
    # 启动 c3,不指定网络,默认使用 bridge 网络
    docker run -d --name c3 registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
    
    # 查看 c2 和 c3 的 IP 地址
    docker exec c2-bridge ip addr show eth0
    docker exec c3 ip addr show eth0
    # 或者使用 ifconfig
    # docker exec c2-bridge ifconfig eth0
    # docker exec c3 ifconfig eth0
    
    你会看到 c2-bridgec3 都获得了 172.17.0.x 网段的 IP 地址,例如 172.17.0.2172.17.0.3。它们可以通过这些 IP 互相 ping 通。

3. host 网络 (--network host)

  • 特点不创建独立的网络命名空间。容器直接共享宿主机的网络栈(网络接口、IP 地址、路由表、端口等)。
  • 原理:容器进程直接使用宿主机的网络接口,就像在宿主机上直接运行的进程一样。
  • 优点
    • 性能最高:网络传输路径最短,没有额外的虚拟化层(如网桥、NAT),接近原生性能。
    • 端口直接暴露:容器内监听的端口直接就是宿主机的端口,无需 -p 映射。
  • 缺点
    • 牺牲隔离性:容器的网络配置与宿主机完全一致,安全性降低。
    • 端口冲突风险:如果多个使用 host 网络的容器(或容器与宿主机上的服务)尝试监听同一个端口,会导致冲突,只有一个能成功启动。
  • 适用场景
    • 对网络性能要求极高的应用(如网络监控、高性能代理)。
    • 需要直接访问宿主机网络服务的容器。
    • 开发或测试环境中,为了方便调试。
  • 示例
    # 启动 c4-host,使用 host 网络
    docker run -d --name c4-host --network host registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
    
    # 查看 c4-host 的网络接口
    docker exec c4-host ip addr show
    # 或者使用 ifconfig
    # docker exec c4-host ifconfig -a
    
    你会发现 c4-host 容器内的网络接口列表与在宿主机上直接运行 ip addr showifconfig -a 的结果完全相同,包括宿主机的物理网卡(如 ens33eth0)、docker0 网桥、lo 回环地址等。如果这个容器内的应用监听了 80 端口,那么你可以直接通过 http://<宿主机IP>:80 访问,无需 -p 映射。

4. container 网络 (--network container:<容器名或ID>)

  • 特点不创建自己的网络命名空间,而是复用另一个已存在容器的网络命名空间。它们共享同一个网络栈(IP 地址、端口、网络接口等)。
  • 原理:新容器加入到目标容器的网络命名空间中。它们共享 lo 接口和目标容器的网络接口。
  • 优点
    • 容器间通信效率高,因为它们在同一个网络命名空间内,可以通过 localhost 直接通信。
    • 适用于需要紧密协作的容器组("Pod" 的概念,类似 Kubernetes Pod 中的容器)。
  • 缺点
    • 生命周期耦合:如果目标容器停止或重启,共享其网络的容器也会失去网络连接(通常需要一起重启)。
    • 端口冲突风险:这两个(或多个)容器不能监听相同的端口。
    • 隔离性降低(相对于 bridge)。
  • 适用场景
    • Sidecar 模式:一个容器作为主应用,另一个容器提供辅助功能(如日志收集、网络代理、监控代理),它们需要通过 localhost 高效通信。
    • 网络调试:启动一个包含网络工具(如 tcpdump, netstat)的容器,并将其附加到另一个应用容器的网络命名空间,以诊断网络问题。
  • 示例
    # 确保目标容器 c3 正在运行 (它是 bridge 网络)
    # docker ps # 确认 c3 在运行
    
    # 启动 c5-container,复用 c3 的网络
    # 注意:通常需要给 sidecar 类容器指定一个不同的入口命令或让其休眠,避免与主容器冲突
    docker run -d --name c5-container --network container:c3 registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 sleep 3600
    
    # 查看 c5-container 的网络接口
    docker exec c5-container ip addr show
    # 或者使用 ifconfig
    # docker exec c5-container ifconfig -a
    
    你会发现 c5-container 的网络接口(特别是 eth0 的 IP 地址和 MAC 地址)与 c3 完全相同。它们共享同一个 IP 172.17.0.3。在 c5-container 内部可以通过 localhost 访问 c3 监听的端口(如果 c3 的应用监听了某个端口的话),反之亦然。

5. 自定义网络 (docker network create ...)

  • 特点:除了上述预定义的网络,Docker 允许用户创建自己的网络,最常用的是自定义 bridge 网络。
  • 原理:类似于默认的 bridge 网络,但提供了更多优势。Docker 会创建一个新的 Linux 网桥,并管理连接到此网络的容器。
  • 优点 (相比默认 bridge 网络)
    • 自动 DNS 解析:连接到同一个自定义 bridge 网络的容器,可以通过容器名称直接互相访问,无需 --link 或 IP 地址。Docker 内置了一个 DNS 服务器来处理这个解析。这是推荐的多容器通信方式。
    • 更好的隔离性:自定义网络提供了比默认 bridge 网络更好的隔离。默认情况下,连接到不同自定义网络的容器不能直接通信(除非特别配置)。
    • 更灵活的网络配置:可以指定子网、网关、IP 范围等。
  • 适用场景
    • 几乎所有多容器应用:当你有多个容器需要互相通信时(例如 Web 应用 + 数据库),强烈推荐使用自定义 bridge 网络。
    • 需要对网络进行更精细控制的场景。
  • 示例
    # 1. 创建一个自定义 bridge 网络 my-app-net
    docker network create my-app-net
    
    # 2. 启动两个容器,并将它们连接到这个网络
    docker run -d --name webapp --network my-app-net nginx:alpine
    docker run -d --name database --network my-app-net redis:alpine
    
    # 3. 在 webapp 容器中,可以直接通过名称 ping通 database
    docker exec webapp ping database
    # PING database (172.x.x.x): 56 data bytes
    # 64 bytes from 172.x.x.x: seq=0 ttl=64 time=0.123 ms
    # ...
    
    # 同样,在 database 容器中也能 ping通 webapp
    docker exec database ping webapp
    

生产环境建议与注意事项

  1. 优先使用自定义 Bridge 网络:对于需要互相通信的多个容器,自定义 Bridge 网络是首选。它提供的容器名 DNS 解析极大地方便了服务发现,且隔离性优于默认 Bridge。
  2. 谨慎使用 Host 网络host 网络性能最佳,但牺牲了安全性和隔离性。仅在确实需要极致网络性能或必须直接访问宿主机网络服务,并且清楚其安全风险时才使用。务必注意端口冲突问题。
  3. 理解 Container 网络container 网络适用于 Sidecar 或调试场景。注意生命周期耦合和端口冲突。
  4. 避免使用默认 Bridge 网络进行容器间通信:虽然技术上可行(通过 IP 或已弃用的 --link),但缺乏 DNS 解析,不如自定义网络方便和健壮。
  5. 管理端口:对于 bridge 和自定义 bridge 网络,使用 -p <宿主机端口>:<容器端口> 来映射端口。对于 hostcontainer 网络,容器直接使用宿主机或目标容器的端口,要确保没有冲突。
  6. None 网络用于特殊场景none 网络适用于不需要网络连接的离线任务或需要完全自定义网络的特殊情况。

总结

Docker 提供了灵活多样的单机网络模式,以满足不同场景的需求:

  • none:完全隔离,无网络。
  • bridge (默认):基础隔离,通过 IP 通信,需端口映射。
  • host:无隔离,高性能,共享宿主机网络,易端口冲突。
  • container:共享另一容器网络,localhost 通信,用于 Sidecar。
  • custom bridge (推荐):良好隔离,容器名 DNS 解析,灵活配置。

理解这些网络模式的原理、优缺点和适用场景,是高效、安全地使用 Docker 的关键一步。在实际生产环境中,强烈推荐优先考虑使用自定义 Bridge 网络来组织你的多容器应用。


希望这篇整理对你和你的粉丝有所帮助!如果你有任何疑问或想法,欢迎在评论区交流!

posted on 2025-04-05 17:31  Leo_Yide  阅读(90)  评论(0)    收藏  举报