网络概述
容器网络指的是容器之间或容器与非 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 | Overlay 网络将多个 Docker 守护进程连接在一起。 |
ipvlan | IPvlan 网络提供对 IPv4 和 IPv6 寻址的完全控制。 |
macvlan | 为容器分配 MAC 地址。 |
有关不同驱动程序的更多信息,请参阅网络驱动程序概述。
连接到多个网络
一个容器可以连接到多个网络。
例如,一个前端容器可以连接到具有外部访问权限的 bridge 网络,以及一个--internal
网络,用于与运行不需要外部网络访问的后端服务的容器通信。
一个容器也可以连接到不同类型的网络。例如,一个 ipvlan
网络用于提供互联网访问,一个 bridge
网络用于访问本地服务。
发送数据包时,如果目的地是直接连接网络中的地址,数据包将被发送到该网络。否则,数据包将被发送到默认网关进行路由。在上面的例子中,ipvlan
网络的网关必须是默认网关。
默认网关由 Docker 选择,并且在容器的网络连接更改时可能会发生变化。要在创建容器或连接新网络时让 Docker 选择特定的默认网关,请设置网关优先级。请参阅 docker run
和 docker network connect
命令的 gw-priority
选项。
默认的 gw-priority
是 0
,优先级最高的网络中的网关是默认网关。因此,如果某个网络应该始终是默认网关,只需将其 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 create
或 docker run
创建或运行容器时,bridge 网络上的容器不会向外部世界暴露任何端口。使用 --publish
或 -p
标志可以将端口提供给 bridge 网络之外的服务。这会在主机中创建防火墙规则,将容器端口映射到 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 主机可用,还对外部世界可用。
如果您在 publish 标志中包含 localhost IP 地址(
127.0.0.1
或::1
),则只有 Docker 主机及其容器可以访问已发布的容器端口。$ docker run -p 127.0.0.1:8080:80 -p '[::1]:8080:80' nginx
警告
同一 L2 段内的宿主机(例如,连接到同一网络交换机的宿主机)可以访问发布到 localhost 的端口。更多信息,请参阅 moby/moby#45610
如果您想让容器对其他容器可见,无需发布容器的端口。您可以通过将容器连接到同一网络(通常是 bridge 网络)来启用容器间通信。
如果在端口映射中没有指定主机 IP,且 bridge 网络仅支持 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 run
或 docker create
命令的标志。下表描述了与 DNS 配置相关的可用 docker run
标志。
标志 | 描述 |
---|---|
--dns | DNS 服务器的 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 文件添加条目。
代理服务器
如果您的容器需要使用代理服务器,请参阅使用代理服务器。