橋接網路驅動程式

在網路方面,網橋網路是一種鏈路層裝置,用於在網段之間轉發流量。網橋可以是硬體裝置,也可以是在主機核心中執行的軟體裝置。

在 Docker 中,網橋網路使用一個軟體網橋,允許連線到同一網橋網路的容器進行通訊,同時提供與未連線到該網橋網路的容器的隔離。Docker 網橋驅動程式會自動在主機中安裝規則,以便不同網橋網路上的容器無法直接相互通訊。

網橋網路適用於在同一個 Docker 守護程式主機上執行的容器。對於在不同 Docker 守護程式主機上執行的容器之間的通訊,您可以在作業系統級別管理路由,或者可以使用覆蓋網路

當您啟動 Docker 時,會自動建立一個預設網橋網路(也稱為 `bridge`),新啟動的容器除非另有指定,否則會連線到它。您還可以建立使用者定義的自定義網橋網路。使用者定義的網橋網路優於預設的 `bridge` 網路。

使用者定義的網橋與預設網橋之間的差異

  • 使用者定義的網橋提供容器間的自動 DNS 解析.

    預設網橋網路上的容器只能透過 IP 地址相互訪問,除非您使用被視為舊版的 `--link` 選項。在使用者定義的網橋網路上,容器可以透過名稱或別名相互解析。

    想象一個包含 Web 前端和資料庫後端的應用程式。如果您將容器命名為 `web` 和 `db`,那麼無論應用程式堆疊在哪臺 Docker 主機上執行,Web 容器都可以透過 `db` 連線到資料庫容器。

    如果您在預設網橋網路上執行相同的應用程式堆疊,則需要手動在容器之間建立連結(使用舊的 `--link` 標誌)。這些連結需要在兩個方向上建立,因此當需要通訊的容器超過兩個時,這會變得很複雜。或者,您也可以操作容器內的 `/etc/hosts` 檔案,但這會產生難以除錯的問題。

  • 使用者定義的網橋提供更好的隔離性.

    所有未指定 `--network` 的容器都會附加到預設網橋網路。這可能存在風險,因為不相關的堆疊/服務/容器隨後能夠相互通訊。

    使用使用者定義的網路提供了一個作用域網路,其中只有附加到該網路的容器才能通訊。

  • 容器可以動態地附加到和分離自使用者定義的網路.

    在容器的生命週期內,您可以動態地將其連線到或斷開與使用者定義網路的連線。要從預設網橋網路中移除容器,您需要停止容器並使用不同的網路選項重新建立它。

  • 每個使用者定義的網路都會建立一個可配置的網橋.

    如果您的容器使用預設網橋網路,您可以對其進行配置,但所有容器都使用相同的設定,例如 MTU 和 `iptables` 規則。此外,配置預設網橋網路是在 Docker 外部進行的,並且需要重新啟動 Docker。

    使用者定義的網橋網路是使用 `docker network create` 建立和配置的。如果不同的應用程式組有不同的網路要求,您可以在建立每個使用者定義的網橋時單獨配置它。

  • 預設網橋網路上鍊接的容器共享環境變數.

    最初,在兩個容器之間共享環境變數的唯一方法是使用 `--link` 標誌將它們連結起來。這種變數共享方式不適用於使用者定義的網路。然而,有更好的方法來共享環境變數。一些思路如下:

    • 多個容器可以使用 Docker 卷掛載包含共享資訊的檔案或目錄。

    • 多個容器可以使用 `docker-compose` 一起啟動,並且 compose 檔案可以定義共享變數。

    • 您可以使用 swarm 服務代替獨立容器,並利用共享的金鑰配置

連線到同一使用者定義網橋網路的容器實際上會向彼此公開所有埠。為了使埠可被不同網路上的容器或非 Docker 主機訪問,該埠必須使用 `-p` 或 `--publish` 標誌進行釋出

選項

下表描述了在使用 `bridge` 驅動程式建立自定義網路時,可以傳遞給 `--opt` 的驅動程式特定選項。

選項預設值描述
com.docker.network.bridge.name建立 Linux 網橋時要使用的介面名稱。
com.docker.network.bridge.enable_ip_masqueradetrue啟用 IP 偽裝。
com.docker.network.bridge.gateway_mode_ipv4
com.docker.network.bridge.gateway_mode_ipv6
nat控制外部連線。請參閱資料包過濾和防火牆
com.docker.network.bridge.enable_icctrue啟用或停用容器間連線。
com.docker.network.bridge.host_binding_ipv4所有 IPv4 和 IPv6 地址繫結容器埠時的預設 IP。
com.docker.network.driver.mtu`0` (無限制)設定容器網路的最大傳輸單元 (MTU)。
com.docker.network.container_iface_prefixeth為容器介面設定自定義字首。
com.docker.network.bridge.inhibit_ipv4false防止 Docker 為網橋分配 IP 地址

其中一些選項也可用作 `dockerd` CLI 的標誌,您可以在啟動 Docker 守護程式時使用它們來配置預設的 `docker0` 網橋。下表顯示了哪些選項在 `dockerd` CLI 中有等效的標誌。

選項標誌
com.docker.network.bridge.name-
com.docker.network.bridge.enable_ip_masquerade--ip-masq
com.docker.network.bridge.enable_icc--icc
com.docker.network.bridge.host_binding_ipv4--ip
com.docker.network.driver.mtu--mtu
com.docker.network.container_iface_prefix-

Docker 守護程式支援一個 `--bridge` 標誌,您可以用它來定義自己的 `docker0` 網橋。如果您想在同一主機上執行多個守護程式例項,請使用此選項。有關詳細資訊,請參閱執行多個守護程式

預設主機繫結地址

當埠釋出選項(如 `-p 80` 或 `-p 8080:80`)中沒有給出主機地址時,預設情況下會在所有主機地址(IPv4 和 IPv6)上提供容器的 80 埠。

網橋網路驅動程式選項 `com.docker.network.bridge.host_binding_ipv4` 可用於修改已釋出埠的預設地址。

儘管選項名稱如此,但也可以指定 IPv6 地址。

當預設繫結地址是分配給特定介面的地址時,容器的埠將只能透過該地址訪問。

將預設繫結地址設定為 `::` 意味著已釋出的埠將僅在主機的 IPv6 地址上可用。但是,將其設定為 `0.0.0.0` 意味著它將在主機的 IPv4 和 IPv6 地址上都可用。

要將已釋出的埠限制為僅 IPv4,必須在容器的釋出選項中包含該地址。例如,`-p 0.0.0.0:8080:80`。

管理使用者定義的網橋

使用 `docker network create` 命令建立一個使用者定義的網橋網路。

$ docker network create my-net

您可以指定子網、IP 地址範圍、閘道器和其他選項。有關詳細資訊,請參閱 docker network create 參考或 `docker network create --help` 的輸出。

使用 `docker network rm` 命令刪除使用者定義的網橋網路。如果當前有容器連線到該網路,請先斷開它們的連線

$ docker network rm my-net

究竟發生了什麼?

當您建立或刪除使用者定義的網橋,或者從使用者定義的網橋連線或斷開容器時,Docker 會使用作業系統特定的工具來管理底層的網路基礎設施(例如在 Linux 上新增或刪除網橋裝置或配置 `iptables` 規則)。這些細節應被視為實現細節。讓 Docker 為您管理使用者定義的網路。

將容器連線到使用者定義的網橋

當您建立新容器時,可以指定一個或多個 `--network` 標誌。此示例將一個 Nginx 容器連線到 `my-net` 網路。它還將容器中的 80 埠釋出到 Docker 主機上的 8080 埠,以便外部客戶端可以訪問該埠。連線到 `my-net` 網路的任何其他容器都可以訪問 `my-nginx` 容器上的所有埠,反之亦然。

$ docker create --name my-nginx \
  --network my-net \
  --publish 8080:80 \
  nginx:latest

要將一個**正在執行**的容器連線到現有的使用者定義網橋,請使用 `docker network connect` 命令。以下命令將一個已經執行的 `my-nginx` 容器連線到一個已存在的 `my-net` 網路:

$ docker network connect my-net my-nginx

從使用者定義的網橋斷開容器連線

要從使用者定義的網橋斷開一個正在執行的容器,請使用 `docker network disconnect` 命令。以下命令將 `my-nginx` 容器從 `my-net` 網路中斷開。

$ docker network disconnect my-net my-nginx

在使用者定義的網橋網路中使用 IPv6

當您建立網路時,可以指定 `--ipv6` 標誌以啟用 IPv6。

$ docker network create --ipv6 --subnet 2001:db8:1234::/64 my-net

如果您不提供 `--subnet` 選項,將自動選擇一個唯一本地地址(ULA)字首。

僅 IPv6 的網橋網路

要跳過網橋及其容器中的 IPv4 地址配置,請使用選項 `--ipv4=false` 建立網路,並使用 `--ipv6` 啟用 IPv6。

$ docker network create --ipv6 --ipv4=false v6net

在預設網橋網路中無法停用 IPv4 地址配置。

使用預設網橋網路

預設的 `bridge` 網路被認為是 Docker 的一個遺留細節,不建議在生產環境中使用。配置它是一個手動操作,並且存在技術缺陷

將容器連線到預設網橋網路

如果您未使用 `--network` 標誌指定網路,並且您指定了網路驅動程式,您的容器預設會連線到 `bridge` 網路。連線到預設 `bridge` 網路的容器可以通訊,但只能透過 IP 地址,除非它們使用舊版的 `--link` 標誌進行連結。

配置預設網橋網路

要配置預設的 `bridge` 網路,您需要在 `daemon.json` 中指定選項。這是一個指定了幾個選項的 `daemon.json` 示例。只指定您需要自定義的設定。

{
  "bip": "192.168.1.1/24",
  "fixed-cidr": "192.168.1.0/25",
  "mtu": 1500,
  "default-gateway": "192.168.1.254",
  "dns": ["10.20.1.2","10.20.1.3"]
}

在此示例中:

  • 網橋的地址是 "192.168.1.1/24" (來自 `bip`)。
  • 網橋網路的子網是 "192.168.1.0/24" (來自 `bip`)。
  • 容器地址將從 "192.168.1.0/25" (來自 `fixed-cidr`) 中分配。

在預設網橋網路中使用 IPv6

可以使用 `daemon.json` 中的以下選項或其命令列等效項為預設網橋啟用 IPv6。

這三個選項僅影響預設網橋,使用者定義的網路不使用它們。以下地址是 IPv6 文件範圍內的示例。

  • 選項 `ipv6` 是必需的。
  • 選項 `bip6` 是可選的,它指定預設網橋的地址,該地址將被容器用作預設閘道器。它還指定了網橋網路的子網。
  • 選項 `fixed-cidr-v6` 是可選的,它指定 Docker 可以自動分配給容器的地址範圍。
    • 字首通常應為 `/64` 或更短。
    • 對於在本地網路上進行實驗,使用唯一本地地址(ULA)字首(匹配 `fd00::/8`)比使用鏈路本地字首(匹配 `fe80::/10`)更好。
  • 選項 `default-gateway-v6` 是可選的。如果未指定,預設值為 `fixed-cidr-v6` 子網中的第一個地址。
{
  "ipv6": true,
  "bip6": "2001:db8::1111/64",
  "fixed-cidr-v6": "2001:db8::/64",
  "default-gateway-v6": "2001:db8:abcd::89"
}

如果未指定 `bip6`,則 `fixed-cidr-v6` 定義了網橋網路的子網。如果未指定 `bip6` 或 `fixed-cidr-v6`,則將選擇一個 ULA 字首。

重新啟動 Docker 以使更改生效。

網橋網路的連線限制

由於 Linux 核心的限制,當 1000 個或更多容器連線到單個網路時,網橋網路會變得不穩定,容器間的通訊可能會中斷。

有關此限制的更多資訊,請參閱 moby/moby#44973

跳過網橋 IP 地址配置

網橋通常被分配網路的 `--gateway` 地址,該地址用作從網橋網路到其他網路的預設路由。

透過 `com.docker.network.bridge.inhibit_ipv4` 選項,您可以建立一個網路,而不會將 IPv4 閘道器地址分配給網橋。如果您想手動為網橋配置閘道器 IP 地址,這將非常有用。例如,如果您將一個物理介面新增到您的網橋,並需要它具有閘道器地址。

使用此配置,除非您已手動在網橋或連線到它的裝置上配置了閘道器地址,否則南北向流量(進出網橋網路的流量)將無法工作。

此選項只能與使用者定義的網橋網路一起使用。

後續步驟