Compare commits
2 Commits
70ed6a6391
...
ef6e6f8206
Author | SHA1 | Date | |
---|---|---|---|
|
ef6e6f8206 | ||
|
1ad20c8004 |
@ -58,7 +58,7 @@ export default defineConfig({
|
||||
collapsed: true,
|
||||
link: '/docs/network/',
|
||||
items: [
|
||||
|
||||
{text: '数据包过滤和防火墙', link: '/docs/network/packet-filtering-firewalls'}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -7,12 +7,12 @@
|
||||
desc: '学习如何为你的发行版安装开源的Docker引擎。'
|
||||
},
|
||||
{
|
||||
href: "baidu.com",
|
||||
href: "/docs/storage/",
|
||||
title: '存储',
|
||||
desc: '使用Docker容器和持久化数据。'
|
||||
},
|
||||
{
|
||||
href: "baidu.com",
|
||||
href: "/docs/network/",
|
||||
title: '网络',
|
||||
desc: '管理容器之间的网络连接。'
|
||||
},
|
||||
|
@ -3,3 +3,145 @@ outline: [2,5]
|
||||
---
|
||||
# 网络概述
|
||||
|
||||
容器网络是指容器相互连接和通信的能力,或连接到非Docker工作负载的能力。
|
||||
|
||||
容器默认启用了网络,并且可以建立出站连接。容器没有关于它连接到哪种网络的信息,或者他们的同行是否也是Docker工作负载的信息。容器只看到具有IP地址、网关、路由表、DNS服务和其他网络详细信息的网络接口。也就是说,除非容器使用`none`网络驱动程序。
|
||||
|
||||
本页从容器的角度描述网络,以及围绕容器网络的概念。本页不介绍有关Docker网络如何工作的操作系统特定细节。有关Docker如何在Linux上操作`iptables`规则的信息,请参阅[数据包过滤和防火墙][0]。
|
||||
|
||||
## 用户定义的网络
|
||||
您可以创建自定义的用户定义网络,并将多个容器连接到同一网络。一旦连接到用户定义的网络,容器可以使用容器IP地址或容器名称相互通信。
|
||||
|
||||
以下示例使用网桥网络驱动程序创建网络,并在创建的网络中运行容器:
|
||||
``` console
|
||||
$ docker network create -d bridge my-net
|
||||
$ docker run --network=my-net -itd --name=container3 busybox
|
||||
```
|
||||
### 驱动器
|
||||
默认情况下,以下网络驱动程序可用,并提供核心网络功能:
|
||||
|
||||
驱动 | 描述
|
||||
| - | - |
|
||||
bridge | 默认网络驱动程序。
|
||||
host | 删除容器和Docker主机之间的网络隔离。
|
||||
none | 将容器与主机和其他容器完全隔离。
|
||||
overlay | 叠加网络将多个Docker守护程序连接在一起。
|
||||
ipvlan | IPvlan网络提供对IPv4和IPv6寻址的完全控制。
|
||||
macvlan | 为容器分配一个MAC地址。
|
||||
有关不同驱动程序的更多信息,请参[阅网络驱动程序概述][1]。
|
||||
|
||||
### 连接到多个网络
|
||||
一个容器可以连接到多个网络。
|
||||
|
||||
例如,前端容器可以连接到具有外部访问的桥接网络,以及一个`--internal`网络,用于与运行不需要外部网络访问的后端服务的容器进行通信。
|
||||
容器也可以连接到不同类型的网络。例如,提供互联网接入的`ipvlan`网络,以及接入本地服务的`bridge`网络。
|
||||
|
||||
发送数据包时,如果目的地是直接连接网络中的地址,则数据包将发送到该网络。否则,数据包会发送到默认网关,以便路由到其目的地。在上述示例中,`ipvlan` 网络的网关必须是默认网关。
|
||||
|
||||
默认网关由Docker选择,每当容器的网络连接发生变化时,可能会发生变化。要让Docker在创建容器或连接新网络时选择特定的默认网关,请设置网关优先级。请参阅 [`docker run`][2] 和 [`docker network connect`][3] 命令的 `gw-priority` 选项。
|
||||
|
||||
默认的 `gw-priority` 为 `0`,网络中具有最高优先级的网关是默认网关。因此,当网络应该始终是默认网关时,将其 `gw-priority` 设置为1就足够了。
|
||||
|
||||
``` console
|
||||
$ 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-搜索`
|
||||
`--dns-option` | `--dns-选项`
|
||||
`--mac-address` | `--mac-地址`
|
||||
`--publish` | `--发布`
|
||||
`--publish-all` | `--全部发布`
|
||||
`--expose` | `--暴露`
|
||||
|
||||
以下示例运行一个 Redis 容器,并将 Redis 绑定到 `localhost`,然后运行 `redis-cli` 命令并通过 `localhost` 接口连接到 Redis 服务器。
|
||||
```console
|
||||
$ 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` 创建或运行容器时,桥接网络上的容器不会向外界公开任何端口。使用 `--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` <br> `-p 8080:80/udp` | 将 Docker 主机上的 TCP 端口 8080 映射到容器中的 TCP 端口 80,并将 Docker 主机上的 UDP 端口 8080 映射到容器中的 UDP 端口 80。
|
||||
|
||||
|
||||
:::tip 重要
|
||||
默认情况下,发布容器端口是不安全的。这意味着,当您发布容器的端口时,它不仅可供 Docker 主机使用,而且可供外部世界使用。
|
||||
|
||||
如果在 publish 标志中包含 localhost IP 地址(`127.0.0.1` 或 `::1`),则只有 Docker 主机及其容器可以访问已发布的容器端口。
|
||||
```console
|
||||
$ docker run -p 127.0.0.1:8080:80 -p '[::1]:8080:80' nginx
|
||||
```
|
||||
:::warning 警告
|
||||
同一 L2 Segment 中的主机(例如,连接到同一 网络交换机)可以访问发布到 localhost 的端口。 有关更多信息,请参阅 [moby/moby#45610][4]
|
||||
|
||||
:::
|
||||
|
||||
如果要使容器可供其他容器访问, 无需发布容器的端口。 您可以通过将容器连接到 同一网络,通常为 [桥接网络][5]。
|
||||
|
||||
如果端口映射中没有给出主机 IP,桥接网络仅限 IPv4,并且 `--userland-proxy=true`(默认),则主机的 IPv6 地址上的端口将映射到容器的 IPv4 地址。
|
||||
|
||||
有关端口映射的更多信息,包括如何禁用它并使用 直接路由到容器,请参阅 [数据包过滤和防火墙][6]。
|
||||
|
||||
## IP 地址和主机名
|
||||
|
||||
创建网络时,IPv4 地址分配默认启用,可以使用 `--ipv4=false` 禁用它。可以使用 `--ipv6` 启用 IPv6 地址分配。
|
||||
|
||||
```console
|
||||
$ 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` 配置文件。连接到默认桥接网络的容器会收到此文件的副本。 附加到 [自定义网络][7] 使用 Docker 的嵌入式 DNS 服务器。 嵌入式 DNS 服务器将外部 DNS 查找转发到主机上配置的 DNS 服务器。
|
||||
|
||||
您可以基于每个容器配置 DNS 解析,使用 `docker run` 或 `docker create` 命令来启动容器。下表描述了与 DNS 配置相关的可用 `docker run` 标志。
|
||||
|
||||
| Flag | 描述 |
|
||||
| - | - |
|
||||
|`--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` 中定义的自定义主机不会由 器皿。要将其他主机传递到容器中,请参阅 [将条目添加到容器主机文件中][8]的 `docker run` 参考文档。
|
||||
|
||||
## 代理服务器
|
||||
如果您的容器需要使用代理服务器,请参阅 [使用代理服务器][9]。
|
||||
|
||||
<!-- 链接 -->
|
||||
[0]:https://docs.docker.com/engine/network/packet-filtering-firewalls/
|
||||
[1]:https://docs.docker.com/engine/network/drivers/
|
||||
[2]:https://docs.docker.com/reference/cli/docker/container/run/
|
||||
[3]:https://docs.docker.com/reference/cli/docker/network/connect/
|
||||
[4]:https://github.com/moby/moby/issues/45610
|
||||
[5]:https://docs.docker.com/engine/network/drivers/bridge/
|
||||
[6]:https://docs.docker.com/engine/network/packet-filtering-firewalls/
|
||||
[7]:https://docs.docker.com/engine/network/tutorials/standalone/#use-user-defined-bridge-networks
|
||||
[8]:https://docs.docker.com/reference/cli/docker/container/run/#add-host
|
||||
[9]:https://docs.docker.com/engine/daemon/proxy/
|
237
docs/network/packet-filtering-firewalls.md
Normal file
237
docs/network/packet-filtering-firewalls.md
Normal file
@ -0,0 +1,237 @@
|
||||
---
|
||||
outline: [2,3]
|
||||
---
|
||||
# 数据包过滤和防火墙
|
||||
在 Linux 上,Docker 会创建 `iptables` 和 `ip6tables` 规则来实现网络隔离、端口发布和过滤。
|
||||
|
||||
由于这些规则是 Docker 桥接网络正常运行所必需的,因此您不应修改 Docker 创建的规则。
|
||||
|
||||
但是,如果您在公开到 Internet 的主机上运行 Docker,则可能需要添加 iptables 策略,以防止未经授权访问主机上运行的容器或其他服务。本页介绍了如何实现此目的,以及您需要注意的注意事项。
|
||||
|
||||
:::info 注意
|
||||
Docker 为网桥网络创建 `iptables` 规则。
|
||||
|
||||
没有为 `ipvlan`、`macvlan` 或主机网络创建 `iptables` 规则。
|
||||
:::
|
||||
|
||||
## Docker 和 iptables 链
|
||||
在 `filter` 表中,Docker 将默认策略设置为 `DROP`,并创建以下自定义 `iptables` 链:
|
||||
- `DOCKER-USER`
|
||||
- 用户定义的规则的占位符,将在 `DOCKER-FORWARD` 和 `DOCKER` 链中的规则之前处理。
|
||||
- `DOCKER-FORWARD`
|
||||
- Docker 网络处理的第一阶段。将与已建立连接无关的数据包传递到其他 Docker 链的规则,以及接受属于已建立连接的数据包的规则。
|
||||
- `DOCKER`
|
||||
- 根据正在运行的容器的端口转发配置,确定是否应接受不属于已建立连接的数据包的规则。
|
||||
- `DOCKER-ISOLATION-STAGE-1` 和 `DOCKER-ISOLATION-STAGE-2`
|
||||
- 将 Docker 网络彼此隔离的规则。
|
||||
- `DOCKER-INGRESS`
|
||||
- 与 Swarm 网络相关的规则。
|
||||
在 `FORWARD` 链中,Docker 添加了无条件跳转到 `DOCKER-USER`、`DOCKER-FORWARD` 和 `DOCKER-INGRESS` 链。
|
||||
|
||||
在 `nat` 表中,Docker 创建链 `DOCKER` 并添加规则以实现伪装和端口映射。
|
||||
|
||||
### 在 Docker 的规则之前添加 iptables 策略
|
||||
被这些自定义链中的规则接受或拒绝的数据包将不会被附加到 `FORWARD` 链的用户定义规则看到。因此,要添加其他规则来筛选这些数据包,请使用 `DOCKER-USER` 链。
|
||||
|
||||
附加到 `FORWARD` 链的规则将在 Docker 的规则之后处理。
|
||||
|
||||
### 匹配请求的原始 IP 和端口
|
||||
当数据包到达 `DOCKER-USER` 链时,它们已经通过 目标网络地址转换 (DNAT) 筛选器。这意味着 `iptables` 标志只能匹配容器的内部 IP 地址和端口。
|
||||
|
||||
如果要根据网络中的原始 IP 和端口匹配流量 请求,您必须使用 [`conntrack` iptables 扩展][1]。例如:
|
||||
|
||||
```console
|
||||
$ sudo iptables -I DOCKER-USER -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
$ sudo iptables -I DOCKER-USER -p tcp -m conntrack --ctorigdst 198.51.100.2 --ctorigdstport 80 -j ACCEPT
|
||||
```
|
||||
|
||||
:::tip 重要
|
||||
使用 `conntrack` 扩展可能会导致性能下降。
|
||||
:::
|
||||
|
||||
## 港口发布和映射
|
||||
|
||||
默认情况下,对于 IPv4 和 IPv6,守护程序会阻止对尚未发布的端口的访问。已发布的容器端口将映射到主机 IP 地址。为此,它使用 iptables 来执行网络地址转换 (NAT)、端口地址转换 (PAT) 和伪装。
|
||||
|
||||
例如,`docker run -p 8080:80 [...]` 在 Docker 主机上任何地址的端口 8080 与容器的端口 80 之间创建映射。来自容器的传出连接将使用 Docker 主机的 IP 地址进行伪装。
|
||||
|
||||
### 限制与容器的外部连接
|
||||
默认情况下,允许所有外部源 IP 连接到已发布到 Docker 主机地址的端口。
|
||||
|
||||
要仅允许特定 IP 或网络访问容器,请在 `DOCKER-USER` 过滤器链的顶部插入一条否定规则。例如,以下规则会丢弃来自除 `192.0.2.2` 之外的所有 IP 地址的数据包:
|
||||
|
||||
```console
|
||||
$ iptables -I DOCKER-USER -i ext_if ! -s 192.0.2.2 -j DROP
|
||||
```
|
||||
|
||||
您需要更改 `ext_if` 以与主机的实际外部接口相对应。您可以改为允许来自源子网的连接。以下规则仅允许来自子网 `192.0.2.0/24` 的访问:
|
||||
|
||||
```console
|
||||
$ iptables -I DOCKER-USER -i ext_if ! -s 192.0.2.0/24 -j DROP
|
||||
```
|
||||
|
||||
最后,您可以使用 `--src-range` 指定要接受的 IP 地址范围 (请记住在使用 `--src-range` 或 `--dst-range` 时还要添加 `-m iprange`):
|
||||
|
||||
```console
|
||||
$ iptables -I DOCKER-USER -m iprange -i ext_if ! --src-range 192.0.2.1-192.0.2.3 -j DROP
|
||||
```
|
||||
|
||||
您可以将 `-s` 或 `--src-range` 与 `-d` 或 `--dst-range` 结合使用来控制两者 源和目标。例如,如果 Docker 主机具有地址 `2001:db8:1111::2` 和 `2001:db8:2222::2` 中,您可以创建特定于 `2001:db8:1111::2` 并将 `2001:db8:2222::2` 保持打开状态。
|
||||
|
||||
`iptables` 很复杂。有关更多信息,请访问 [Netfilter.org HOWTO][2]。
|
||||
|
||||
|
||||
### 直接路由
|
||||
端口映射可确保在主机的网络地址上访问已发布的端口,这些地址可能可供任何外部客户端路由。通常不会在主机网络中为主机中存在的容器地址设置路由。
|
||||
|
||||
但是,特别是对于 IPv6,您可能更愿意避免使用 NAT,而是安排到容器地址的外部路由(“direct routing 直接路由”)。
|
||||
|
||||
要从 Docker 主机外部访问桥接网络上的容器,您必须通过 Docker 主机上的地址设置到桥接网络的路由。这可以使用静态路由、边界网关协议 (BGP) 或适合您的网络的任何其他方式来实现。
|
||||
|
||||
在本地第 2 层网络中,远程主机可以使用本地网络上的 Docker 守护程序主机地址设置到容器网络的静态路由。这些主机可以直接访问容器。对于本地网络之外的远程主机,直接访问容器需要配置路由器才能启用必要的路由。
|
||||
|
||||
#### 网关模式
|
||||
桥接网络驱动程序具有以下选项:
|
||||
- `com.docker.network.bridge.gateway_mode_ipv6`
|
||||
- `com.docker.network.bridge.gateway_mode_ipv4`
|
||||
|
||||
这些模式中的每一个都可以设置为网关模式之一:
|
||||
|
||||
- `nat` (国家)
|
||||
- `nat-unprotected` (nat-未受保护)
|
||||
- `routed` (路由)
|
||||
- `isolated` (孤立)
|
||||
|
||||
默认值为 `NAT`,为每个已发布的容器端口设置伪装规则。离开主机的数据包将使用主机地址。
|
||||
|
||||
使用 mode `routed` 时,不会设置 NAT 或伪装规则,但会设置 `iptables` 仍会进行设置,以便只能访问已发布的容器端口。 来自容器的传出数据包将使用容器的地址 不是主机地址。
|
||||
|
||||
在 `nat` 模式下,当端口发布到特定主机地址时,该端口只能通过具有该地址的主机接口访问。因此,例如,将端口发布到环回接口上的地址意味着远程主机无法访问它。
|
||||
|
||||
但是,使用直接路由时,除非 Docker 主机的防火墙有其他限制,否则始终可以从远程主机访问已发布的容器端口。本地第 2 层网络上的主机可以设置直接路由,而无需任何其他网络配置。本地网络外部的主机只有在网络的路由器配置为启用直接路由到容器时,才能使用直接路由到容器。
|
||||
|
||||
在 `nat-unprotected` 模式下,也可以使用直接路由访问未发布的容器端口,无需设置端口筛选规则。包含此模式是为了与传统的默认行为兼容。
|
||||
|
||||
网关模式还会影响连接到同一主机上不同 Docker 网络的容器之间的通信。
|
||||
|
||||
- 在 `nat` 和 `nat-unprotected` 模式下,其他桥接网络中的容器只能通过它们发布到的主机地址访问已发布的端口。不允许来自其他网络的直接路由。
|
||||
- 在 `routed 路由模` 式下,其他网络中的容器可以使用直接路由来访问端口,而无需通过主机地址。
|
||||
|
||||
在路由模式下,不使用 `-p` 或 `--publish` 端口映射中的主机端口,主机地址仅用于决定是将映射应用于 IPv4 还是 IPv6。因此,当映射仅适用于 `routed 路由` 的 mode,只应使用地址 `0.0.0.0` 或`::` ,并且不应给出 host 端口。如果给出了特定地址或端口,则它对已发布的端口没有影响,并且将记录一条警告消息。
|
||||
|
||||
仅当网络也是使用 CLI 标志 `--internal` 或等效项创建时,才能使用模式隔离。地址通常分配给内部网络中的桥接设备。因此,docker 主机上的进程可以访问网络,并且网络中的容器可以访问侦听该桥接地址的主机服务(包括侦听“任何”主机地址 `0.0.0.0` 或 `::`) 的服务)。在 `isolated 网关模式隔离` 的情况下创建网络时,不会为网桥分配地址。
|
||||
|
||||
##### 例
|
||||
创建适合 IPv6 直接路由的网络,并为 IPv4 启用 NAT:
|
||||
```console
|
||||
$ docker network create --ipv6 --subnet 2001:db8::/64 -o com.docker.network.bridge.gateway_mode_ipv6=routed mynet
|
||||
```
|
||||
|
||||
创建具有已发布端口的容器:
|
||||
|
||||
```console
|
||||
$ docker run --network=mynet -p 8080:80 myimage
|
||||
```
|
||||
|
||||
然后:
|
||||
|
||||
- 对于 IPv4 和 IPv6,将仅打开容器端口 80。如果有到容器地址的路由,并且主机的防火墙没有阻止访问,则可以从任何地方访问它。
|
||||
- 对于 IPv6,使用 `routed 路由` 模式时,将在容器的 IP 地址上打开端口 80。端口 8080 不会在主机的 IP 地址上打开,传出数据包将使用容器的 IP 地址。
|
||||
- 对于 IPv4,使用默认的 `nat` 模式,容器的端口 80 将通过主机 IP 地址上的端口 8080 访问,也可以直接访问。源自容器的连接将使用主机的 IP 地址进行伪装。
|
||||
|
||||
在 `docker inspect` 中,此端口映射将显示如下。请注意,IPv6 没有 `HostPort`,因为它使用的是 `routed 路由`模式:
|
||||
```console
|
||||
$ docker container inspect <id> --format "{{json .NetworkSettings.Ports}}"
|
||||
{"80/tcp":[{"HostIp":"0.0.0.0","HostPort":"8080"},{"HostIp":"::","HostPort":""}]}
|
||||
```
|
||||
|
||||
或者,要使映射仅 IPv6,禁用对容器端口 80 的 IPv4 访问,请使用未指定的 IPv6 地址 `[::]`,并且不要包含主机端口号:
|
||||
```console
|
||||
$ docker run --network mynet -p '[::]::80'
|
||||
```
|
||||
|
||||
### 设置容器的默认绑定地址
|
||||
默认情况下,当容器的端口映射时没有任何特定的主机地址,Docker 守护程序会将已发布的容器端口绑定到所有主机地址(`0.0.0.0` 和 `[::]`)。
|
||||
|
||||
例如,以下命令将端口 8080 发布到主机上的所有网络接口,包括 IPv4 和 IPv6 地址,从而可能使它们可供外部使用。
|
||||
|
||||
```bash
|
||||
docker run -p 8080:80 nginx
|
||||
```
|
||||
您可以更改已发布容器端口的默认绑定地址,以便默认情况下只有 Docker 主机可以访问它们。为此,您可以将守护程序配置为使用环回地址 (`127.0.0.1`)。
|
||||
|
||||
:::warning 警告
|
||||
在低于 28.0.0 的版本中,同一 L2 分段中的主机(例如 主机连接到同一网络交换机)可以访问发布到 localhost 中。有关更多信息,请参阅 [moby/moby#45610][3]
|
||||
:::
|
||||
|
||||
要为用户定义的桥接网络配置此设置,请在创建网络时使用
|
||||
要为用户定义的桥接网络配置此设置,请在创建网络时使用` com.docker.network.bridge.host_binding_ipv4` [驱动程序选项][4]。
|
||||
|
||||
```console
|
||||
$ docker network create mybridge \
|
||||
-o "com.docker.network.bridge.host_binding_ipv4=127.0.0.1"
|
||||
```
|
||||
|
||||
:::info 注意
|
||||
将默认绑定地址设置为 `::` 表示未指定主机地址的端口绑定将适用于主机上的任何 IPv6 地址。但是,`0.0.0.0` 指任何 IPv4 或 IPv6 地址。
|
||||
|
||||
更改默认绑定地址对 Swarm 服务没有任何影响。Swarm 服务始终在 `0.0.0.0` 网络接口上公开。
|
||||
:::
|
||||
|
||||
#### 默认网桥
|
||||
要为默认桥接网络设置默认绑定,请配置 `“ip”` `daemon.json`键:
|
||||
|
||||
```json
|
||||
{
|
||||
"ip": "127.0.0.1"
|
||||
}
|
||||
```
|
||||
|
||||
这会将默认桥接网络上已发布容器端口的默认绑定地址更改为 `127.0.0.1`。重新启动守护程序以使此更改生效。或者,您可以在启动守护程序时使用 `dockerd --ip` 标志。
|
||||
|
||||
## 路由器上的 Docker
|
||||
|
||||
在 Linux 上,Docker 需要在主机上启用 “IP 转发”。因此,它会启用 `sysctl` 设置 `net.ipv4.ip_forward` 和 `net.ipv6.conf.all.forwarding` 在启动时,它们尚未启用。当它这样做时,它也 将 iptables `FORWARD` 链的策略设置为 `DROP`。
|
||||
|
||||
如果 Docker 将 `FORWARD` 链的策略设置为 `DROP`。这将阻止您的 Docker 主机充当路由器,这是启用 IP 转发时的推荐设置。
|
||||
|
||||
要阻止 Docker 将 `FORWARD` 链的策略设置为 `DROP`,请包含 `"ip-forward-no-drop":true` 在 `/etc/docker/daemon.json` 中,或添加选项 `--ip-forward-no-drop` 添加到 `dockerd` 命令行。
|
||||
|
||||
或者,您可以为要转发的数据包将 `ACCEPT` 规则添加到 `DOCKER-USER` 链中。例如:
|
||||
|
||||
```console
|
||||
$ iptables -I DOCKER-USER -i src_if -o dst_if -j ACCEPT
|
||||
```
|
||||
|
||||
:::warning 警告
|
||||
在 28.0.0 之前的版本中,Docker 始终将 IPv6 `FORWARD` 链的默认策略设置为 `DROP`。在版本 28.0.0 及更高版本中,只有在启用 IPv6 转发本身时,它才会设置该策略。这一直是 IPv4 转发的行为。
|
||||
|
||||
如果在 Docker 启动之前在主机上启用了 IPv6 转发,请检查主机的配置以确保它仍然安全。
|
||||
:::
|
||||
|
||||
## 防止 Docker 操作 iptables
|
||||
可以在守护进程配置中将 `iptables` 或 `ip6tables` 设置为 `false` ,但此选项对大多数用户来说并不合适,可能会破坏 Docker 引擎的容器网络。
|
||||
|
||||
所有容器的所有端口都将从网络中访问,并且不会从 Docker 主机 IP 地址映射。
|
||||
|
||||
无法完全阻止 Docker 创建 iptables 规则,而且在事后创建规则极其复杂,超出了这些说明的范围。
|
||||
|
||||
## 集成 firewalld
|
||||
如果你使用了 `iptables` 选项设置为 `true` ,并且系统启用了 `firewalld`,Docker 会自动创建一个名为 `docker` 的目标 `ACCEPT` 的 `firewalld` 区域。
|
||||
|
||||
Docker 创建的所有网络接口(例如, `docker0` )都会插入到 `docker` 区域中。
|
||||
|
||||
Docker 也创建了一个转发策略 `docker-forwarding` ,允许从 `ANY` 区域转发到 `docker` 区域。
|
||||
|
||||
## Docker 和 ufw
|
||||
Uncomplicated Firewall (ufw) 是 Debian 和 Ubuntu 的前端工具,允许您管理防火墙规则。Docker 和 ufw 以使它们彼此不兼容的方式使用 iptables。
|
||||
|
||||
当您使用 Docker 发布容器端口时,该容器的流量会在通过 ufw 防火墙设置之前被重定向。Docker 将容器流量路由到 `nat` 表中,这意味着数据包在到达 ufw 使用的 `INPUT` 和 `OUTPUT` 链之前就被重定向了。数据包在防火墙规则可以应用之前就被路由了,实际上忽略了您的防火墙配置。
|
||||
|
||||
|
||||
|
||||
<!-- 链接 -->
|
||||
[1]:https://ipset.netfilter.org/iptables-extensions.man.html#lbAO
|
||||
[2]:https://www.netfilter.org/documentation/HOWTO/NAT-HOWTO.html
|
||||
[3]:https://github.com/moby/moby/issues/45610
|
||||
[4]:https://docs.docker.com/engine/network/drivers/bridge/#options
|
Loading…
Reference in New Issue
Block a user