网络概览

容器网络是指容器连接到并相互通信,或与非 Docker 工作负载通信的能力。

容器默认启用网络,并且可以建立出站连接。容器没有关于其附加到哪种网络的信息,也不知道其对等方是否也是 Docker 工作负载。容器只能看到一个带有 IP 地址、网关、路由表、DNS 服务和其他网络细节的网络接口。除非容器使用 none 网络驱动程序。

本页从容器的角度描述网络以及围绕容器网络的概念。本页不描述有关 Docker 网络如何工作的特定于操作系统的详细信息。有关 Docker 如何在 Linux 上操作 iptables 规则的信息,请参阅数据包过滤和防火墙

用户定义的网络

您可以创建自定义的用户定义网络,并将多个容器连接到同一个网络。一旦连接到用户定义的网络,容器就可以使用容器 IP 地址或容器名称相互通信。

以下示例使用 bridge 网络驱动程序创建一个网络,并在创建的网络中运行一个容器

$ docker network create -d bridge my-net
$ docker run --network=my-net -itd --name=container3 busybox

驱动程序

以下网络驱动程序默认可用,并提供核心网络功能

驱动程序描述
bridge默认网络驱动程序。
host移除容器和 Docker 主机之间的网络隔离。
none将容器与主机和其他容器完全隔离。
overlay覆盖网络将多个 Docker 守护进程连接在一起。
ipvlanIPvlan 网络提供对 IPv4 和 IPv6 寻址的完全控制。
macvlan为容器分配一个 MAC 地址。

有关不同驱动程序的更多信息,请参阅网络驱动程序概述

连接到多个网络

一个容器可以连接到多个网络。

例如,一个前端容器可以连接到一个具有外部访问权限的桥接网络,以及一个用于与运行后端服务的容器通信的--internal网络,这些后端服务不需要外部网络访问。

一个容器也可以连接到不同类型的网络。例如,一个 ipvlan 网络用于提供互联网访问,而一个 bridge 网络用于访问本地服务。

发送数据包时,如果目标是直接连接网络中的地址,数据包将发送到该网络。否则,数据包将发送到默认网关以路由到其目标。在上面的示例中,ipvlan 网络的网关必须是默认网关。

默认网关由 Docker 选择,并且可能在容器的网络连接发生变化时改变。要在创建容器或连接新网络时让 Docker 选择特定的默认网关,请设置网关优先级。请参阅 docker rundocker network connect 命令的 gw-priority 选项。

默认的 gw-priority0,具有最高优先级的网络中的网关是默认网关。因此,当一个网络应该始终是默认网关时,将其 gw-priority 设置为 1 就足够了。

$ docker run --network name=gwnet,gw-priority=1 --network anet1 --name myctr myimage
$ docker network connect anet2 myctr

容器网络

除了用户定义的网络之外,您还可以使用 --network container:<name|id> 标志格式将一个容器直接附加到另一个容器的网络堆栈。

对于使用 container: 网络模式的容器,不支持以下标志

  • --add-host
  • --hostname
  • --dns
  • --dns-search
  • --dns-option
  • --mac-address
  • --publish
  • --publish-all
  • --expose

以下示例运行一个 Redis 容器,其中 Redis 绑定到 localhost,然后运行 redis-cli 命令并通过 localhost 接口连接到 Redis 服务器。

$ docker run -d --name redis example/redis --bind 127.0.0.1
$ docker run --rm -it --network container:redis example/redis-cli -h 127.0.0.1

已发布的端口

默认情况下,当您使用 docker createdocker run 创建或运行容器时,桥接网络上的容器不会向外界暴露任何端口。使用 --publish-p 标志使端口可用于桥接网络之外的服务。这会在主机中创建一个防火墙规则,将容器端口映射到 Docker 主机上的一个端口,以供外界访问。以下是一些示例

标志值描述
-p 8080:80将 Docker 主机上的 8080 端口映射到容器中的 TCP 80 端口。
-p 192.168.1.100:8080:80将 Docker 主机 IP 192.168.1.100 上的 8080 端口映射到容器中的 TCP 80 端口。
-p 8080:80/udp将 Docker 主机上的 8080 端口映射到容器中的 UDP 80 端口。
-p 8080:80/tcp -p 8080:80/udp将 Docker 主机上的 TCP 8080 端口映射到容器中的 TCP 80 端口,并将 Docker 主机上的 UDP 8080 端口映射到容器中的 UDP 80 端口。
重要

发布容器端口默认是不安全的。这意味着,当您发布一个容器的端口时,它不仅对 Docker 主机可用,也对外部世界可用。

如果您在发布标志中包含 localhost IP 地址(127.0.0.1::1),则只有 Docker 主机及其容器可以访问已发布的容器端口。

$ docker run -p 127.0.0.1:8080:80 -p '[::1]:8080:80' nginx
警告

在 28.0.0 之前的版本中,同一 L2 网段内的主机(例如,连接到同一网络交换机的主机)可以访问发布到 localhost 的端口。有关更多信息,请参阅 moby/moby#45610

如果您想让一个容器可以被其他容器访问,则不必发布该容器的端口。您可以通过将容器连接到同一个网络(通常是桥接网络)来启用容器间通信。

如果端口映射中未给出主机 IP,桥接网络仅为 IPv4,且 --userland-proxy=true(默认),则主机 IPv6 地址上的端口将映射到容器的 IPv4 地址。

有关端口映射的更多信息,包括如何禁用它以及使用直接路由到容器的方法,请参阅数据包过滤和防火墙

IP 地址和主机名

创建网络时,默认启用 IPv4 地址分配,可以使用 --ipv4=false 禁用。可以使用 --ipv6 启用 IPv6 地址分配。

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

默认情况下,容器会为其附加的每个 Docker 网络获取一个 IP 地址。容器从网络的 IP 子网中接收一个 IP 地址。Docker 守护进程为容器执行动态子网划分和 IP 地址分配。每个网络还有一个默认的子网掩码和网关。

您可以将一个正在运行的容器连接到多个网络,方法是在创建容器时多次传递 --network 标志,或者对已在运行的容器使用 docker network connect 命令。在这两种情况下,您都可以使用 --ip--ip6 标志来指定容器在该特定网络上的 IP 地址。

同样,容器的主机名默认为 Docker 中的容器 ID。您可以使用 --hostname 覆盖主机名。当使用 docker network connect 连接到现有网络时,您可以使用 --alias 标志为该网络上的容器指定一个额外的网络别名。

DNS 服务

默认情况下,容器使用与主机相同的 DNS 服务器,但您可以使用 --dns 覆盖此设置。

默认情况下,容器继承 /etc/resolv.conf 配置文件中定义的 DNS 设置。附加到默认 bridge 网络的容器会收到此文件的一个副本。附加到自定义网络的容器使用 Docker 的嵌入式 DNS 服务器。嵌入式 DNS 服务器将外部 DNS 查找转发到主机上配置的 DNS 服务器。

您可以在每个容器的基础上配置 DNS 解析,方法是使用用于启动容器的 docker rundocker create 命令的标志。下表描述了与 DNS 配置相关的可用 docker run 标志。

标志描述
--dnsDNS 服务器的 IP 地址。要指定多个 DNS 服务器,请使用多个 --dns 标志。DNS 请求将从容器的网络命名空间转发,因此,例如,--dns=127.0.0.1 指的是容器自己的环回地址。
--dns-search一个 DNS 搜索域,用于搜索非完全限定的主机名。要指定多个 DNS 搜索前缀,请使用多个 --dns-search 标志。
--dns-opt表示 DNS 选项及其值的键值对。有关有效选项,请参阅您操作系统的 resolv.conf 文档。
--hostname容器为自己使用的主机名。如果未指定,则默认为容器的 ID。

自定义主机

您的容器将在 /etc/hosts 中包含定义容器本身主机名以及 localhost 和其他一些常见内容的行。在主机上 /etc/hosts 中定义的自定义主机不会被容器继承。要将其他主机传递到容器中,请参阅 docker run 参考文档中的向容器 hosts 文件添加条目

代理服务器

如果您的容器需要使用代理服务器,请参阅使用代理服务器

© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.