返回首页

Docker容器网络详解:实用指南

本全面指南从基础开始讲解Docker容器网络,涵盖默认桥接的局限性、用户定义桥接的优势、关键网络驱动、DNS服务发现、端口发布以及实际配置步骤。它为开发人员和系统管理员提供构建安全、隔离且可扩展的容器化应用所需的知识。

Docker网络:容器完全指南
Advertisement 728x90

Docker 容器网络:实用指南

当你开始使用 Docker 时,首先遇到的复杂问题之一就是容器如何相互通信以及与外部世界通信。简单来说,Docker 容器网络就是一套虚拟网络和规则系统,它实现了这种通信,为你的容器化应用提供隔离、安全和连接性。理解这些概念不仅仅是理论上的需求,更是构建安全、可扩展且易于维护的容器部署的基础。

你将学到什么

你将理解 Docker 网络模型的核心概念,从默认桥接到专用驱动程序,并学习如何为你的容器配置安全、隔离的网络。最终,你将能够设计网络拓扑结构,隔离敏感服务,实现无缝的服务发现,并排查常见的连接问题。关键要点是:对于大多数生产用例,用户定义的桥接网络远优于默认桥接网络

Docker 网络的核心

从根本上说,容器网络指的是容器之间以及与非 Docker 网络服务进行连接和通信的能力。默认情况下,容器启用了网络功能,可以发起出站连接。容器会看到一个带有 IP 地址、网关、路由表和 DNS 服务的网络接口,但它不知道自己所连接的网络类型,也不知道其对等节点是否也是 Docker 容器。

Google AdInline article slot

当 Docker 引擎在 Linux 上首次启动时,它会创建一个名为“默认桥接”网络的内置网络。如果你在运行容器时没有使用 --network 选项,它就会连接到这个默认桥接网络。虽然这个默认设置可以工作,但它有显著的局限性,最明显的是容器之间缺乏自动 DNS 解析。

用户定义的桥接网络:更优的选择

对于任何严肃的应用,你都应该创建用户定义的桥接网络。这些自定义网络相比默认桥接网络提供了几个关键优势:

  1. 自动 DNS 解析:用户定义桥接网络上的容器可以通过容器名称或别名相互解析。例如,一个 web 容器只需使用主机名 db 即可连接到 db 容器。这在默认桥接网络上是不可能的,它需要使用传统的 --link 标志或手动操作 /etc/hosts 文件。

    Google AdInline article slot
  2. 更好的隔离性:所有未指定 --network 的容器都会连接到默认桥接网络,这会造成不相关的容器之间可以通信的风险。用户定义的网络提供了一个有作用域的网络,除非显式连接,否则容器之间相互隔离。

  3. 随时连接和断开:你可以将正在运行的容器连接到用户定义的网络或从中断开,而无需重启它。要更改默认桥接网络上容器的网络,你必须停止并重新创建它。

  4. 可配置的桥接:每个用户定义的网络都可以配置自己的设置(如 MTU 和防火墙规则),允许你为不同的应用需求定制网络。

    Google AdInline article slot

如何创建和使用自定义桥接网络

创建和使用自定义桥接网络非常简单。这是构建安全且可管理的 Docker 网络设置的基础。

步骤 1:创建网络。

docker network create my-secure-network

默认情况下,这会创建一个桥接网络。你也可以使用 -d 标志指定驱动程序(例如,docker network create -d bridge my-net)。

步骤 2:在此网络上运行容器。

docker run -d --name web --network my-secure-network nginx
docker run -d --name db --network my-secure-network postgres

现在,web 容器可以使用主机名 dbdb 容器通信。

步骤 3:将正在运行的容器连接到网络。

docker network connect my-secure-network already-running-container

一个容器可以同时连接到多个网络,这是一个强大的功能,可用于创建复杂的网络模式,例如前端同时连接到面向外部的网络和内部后端网络。

关键网络驱动程序及其用例

Docker 的网络是可插拔的,使用驱动程序来提供核心功能。以下是你会遇到的主要驱动程序的详细说明。

驱动程序 描述 最适合
bridge 默认的网络驱动程序。在主机上创建一个私有内部网络。 单主机应用,其中容器需要相互通信。这是标准且最常见的选择。
host 移除网络隔离。容器直接共享主机的网络栈。 性能关键型应用或需要管理大量端口或网络级操作的服务(例如,像 Pi-hole 这样的网络级 DNS/DHCP 服务器)。安全警告: 此模式移除了一个关键的隔离层。
none 禁用容器的网络功能。它只有一个回环接口(lo)。 高度隔离的任务,如离线批处理或不需要任何网络访问的任务。
overlay 连接多个 Docker 守护进程,实现跨主机通信。 Docker Swarm 集群和多主机应用。
macvlan 为容器分配一个 MAC 地址,使其在你的网络上显示为一个物理设备。 遗留应用或虚拟机迁移,其中容器需要直接位于物理网络上。
ipvlan 类似于 macvlan,但没有唯一的 MAC 地址,可以完全控制 IPv4/IPv6 寻址。 网络环境,其中对可分配的 MAC 地址数量有限制。

对于大多数开发者来说,bridge 驱动程序——特别是用户定义的桥接——将是他们工具箱中的主要工具。

深入理解主机模式

host 网络驱动程序是一个强大但专用的工具。它移除了容器与 Docker 主机之间的网络隔离,这意味着容器直接使用主机的网络栈。正如一位实践者所指出的,这对于需要处理广播流量的服务(如 DNS 和 DHCP 服务)来说是理想的选择。

⚠️ 重要警告:主机网络不跨平台友好。它仅在 Linux 主机上按预期工作。在 macOS 和 Windows 上(通过 Docker Desktop),由于虚拟机实现,它的行为会有所不同。此外,你会失去为容器使用 Docker DNS 服务发现的能力,并且在主机模式下无法将其连接到其他网络。

Docker Compose 示例:

version: "3"
services:
  web:
    image: nginx:latest
    network_mode: host

此容器将直接在你的主机 IP 地址上访问。不需要 ports 指令。

发布端口:将容器连接到外部世界

默认情况下,桥接网络上的端口无法从主机外部访问。要使服务对外部可用,你需要使用 -p--publish 标志发布端口。

docker run -d -p 8080:80 --name webserver nginx

这将 Docker 主机上的端口 8080 映射到容器中的端口 80。发往主机 IP 地址端口 8080 的流量将被转发到容器。

  • 要发布所有暴露的端口,请使用 -P 标志。
  • 要限制仅本地主机访问,请发布到 127.0.0.1docker run -p 127.0.0.1:8080:80 nginx
  • 需要注意的是,对于同一桥接网络上的容器,你不需要发布端口来让它们相互通信;它们可以直接使用容器名称和端口进行通信。

DNS 和服务发现

默认情况下,容器继承 Docker 主机的 DNS 设置。然而,存在一个关键区别:

  • 默认桥接网络:容器接收主机 /etc/resolv.conf 文件的副本。
  • 用户定义的网络:容器使用 Docker 内嵌的 DNS 服务器,地址为 127.0.0.11。此服务器将外部 DNS 查询转发到主机配置的服务器。这个内嵌的 DNS 正是实现神奇的容器名称解析的原因。如果容器内的应用需要显式查询 Docker DNS 服务器,它应该使用地址 127.0.0.11

你可以使用 --dns--dns-search--dns-opt 等标志在每个容器的基础上覆盖 DNS 设置。

实用工作流程:更改容器的网络

可以更改容器的网络配置,但存在重要的限制。

  1. 对于桥接网络上的容器:你可以随时将其连接到网络或从中断开。

    # 将正在运行的容器连接到自定义网络
    docker network connect my-new-network my-container
    # 将其从默认桥接网络断开
    docker network disconnect bridge my-container

    你不能将容器从其最后一个网络断开;它必须始终连接到至少一个网络。

  2. 对于主机网络上的容器不可能在其运行时更改其网络配置或将其连接到另一个网络。如果你尝试,会遇到错误:

    Error response from daemon: container sharing network namespace with another container or host cannot be connected to any other network

    要更改其网络,你必须停止、移除并重新创建容器,通过使用相同的环境变量、卷和其他设置来保留其配置。

常见问题解答

默认桥接网络和用户定义的桥接网络有什么区别? 最重要的区别是自动 DNS 解析:用户定义桥接网络上的容器可以通过容器名称通信,而默认桥接网络上的容器只能通过 IP 地址相互访问。用户定义的网络还提供更好的隔离性和随时连接/断开容器的灵活性。

如何使容器可以从我的本地网络或互联网访问? 你必须使用 -p--publish 标志发布容器的端口。例如,-p 8080:80 将 Docker 主机上的端口 8080 映射到容器中的端口 80,使服务在你的主机 IP 地址上可用。

我可以将一个容器连接到多个网络吗? 是的,这是一个强大的功能。一个容器可以同时连接到多个网络,方法是在创建时多次使用 --network 标志,或者对正在运行的容器使用 docker network connect 命令。这对于创建既有面向外部网络又有内部私有网络的应用非常有用。

为什么我不能从 Docker 主机 ping 我的容器? 在 Docker Desktop for Mac 和 Windows 上,由于虚拟机中网络实现的方式,你无法直接从主机 ping Linux 容器。这是一个已知的限制,并且 docker0 桥接接口在主机上不可见。但是,Windows 用户可以 ping Windows 容器。

我什么时候应该使用 host 网络驱动程序? 你应该仅在特定用例中使用 host 驱动程序,例如原生网络性能至关重要,或者服务需要处理网络级功能(如 DNS/DHCP 服务器)。这会牺牲安全性和可移植性,因为它仅在 Linux 上可靠工作,并且移除了网络隔离。

来源

— Editorial Team

Advertisement 728x90

继续阅读