<!-- review: reviewed -->

<a id="http-docker"></a>

# Docker

该模块基于 Docker 容器标签，在 [HTTP](https://cn.angie.software//angie/docs/configuration/modules/http/http_upstream.md#u-upstream) 和 [stream](https://cn.angie.software//angie/docs/configuration/modules/stream/stream_upstream.md#s-u-upstream) 上下文中提供代理服务器组的动态配置。
要使该功能正常工作，必须在组中配置共享内存区域（参见 [http](https://cn.angie.software//angie/docs/configuration/modules/http/http_upstream.md#u-zone) 和 [stream](https://cn.angie.software//angie/docs/configuration/modules/stream/stream_upstream.md#s-u-zone) 的 `zone` 说明）。

#### NOTE
该模块支持与 Docker 及其替代品（如 Podman）配合使用，这些替代品实现了兼容的 API。

该模块通过 API 连接到 Docker 守护进程，与其交互的方法由 [docker_endpoint](#docker-endpoint) 指令指定。
在获取正在运行的容器列表后，Angie 会分析它们是否存在合适的 [标签](#docker-labels)。
如果容器描述中包含带有端口的标签，则该容器的地址和端口，以及该容器其他标签中的参数，将自动添加到 Angie 配置中相应的 `upstream` 块。

#### NOTE
同一个容器可以添加到多个 `upstream` 组。
要实现这一点，只需指定多组具有不同组名和端口的标签即可。

这在容器在不同端口上运行多个不同服务时特别有用——每个服务可以关联到自己的组。

然后，该模块订阅容器生命周期事件，并开始在不重新加载 Angie 的情况下更新代理服务器配置：

- 当启动带有合适标签的容器时，其内部 IP 地址将添加到指定的组；
- 当停止或删除容器时，它会自动从组中移除；
- 当使用 **docker pause** 命令暂停容器时，服务器被标记为 `down`，使用 **docker unpause** 时——标记为 `up`。

<a id="configuration-example-12"></a>

## 配置示例

该模块的指令始终位于 `http` 上下文中，但代理服务器组可以在 `http` 上下文和 `stream` 上下文中定义。

`http` 的配置示例：

```nginx
http {

    # 连接选项示例：
    # docker_endpoint http://127.0.0.1:2375;
    # docker_endpoint https://127.0.0.1:2376;
    docker_endpoint unix:/var/run/docker.sock;

    # Docker 响应缓冲区最大大小（可选）
    # docker_max_object_size 128k;

    upstream u {

        zone z 1m; # 需要共享内存区域
    }

    server {

        listen 80;
        server_name example.com;

        location / {

            proxy_pass http://u;
        }
    }
}
```

stream 上下文中的类似配置：

```nginx
http {

    # 连接选项示例：
    # docker_endpoint http://127.0.0.1:2375;
    # docker_endpoint https://127.0.0.1:2376;
    docker_endpoint unix:/var/run/docker.sock;

    # Docker 响应缓冲区最大大小（可选）
    # docker_max_object_size 128k;
}

stream {

    upstream u {

        zone z 1m;
    }

    server {

        listen 12345;
        proxy_pass u;
    }
}
```

收到容器事件后，Angie 会查找形式为 `angie.http.upstreams.<name>.port=<port>` （用于 HTTP 上下文）或 `angie.stream.upstreams.<name>.port=<port>` （用于 stream 上下文）的标签。
当存在标签时，容器在指定 Docker 网络中的地址（如果未指定 `angie.network` 标签，则为第一个可用的地址）将添加到相应的代理服务器组。

如果容器停止或被删除，服务器将从组中移除；如果容器被暂停，服务器将被标记为 `down`。

Angie 识别的带有标签的 `docker-compose.yml` 文件片段：

```yaml
services:
  myapp:
    image: myapp:latest
    labels:
      - "angie.http.upstreams.u.port=8080"
      - "angie.network=my_bridge"
      - "angie.http.upstreams.u.weight=2"
      - "angie.http.upstreams.u.max_conns=50"
      - "angie.http.upstreams.u.max_fails=3"
      - "angie.http.upstreams.u.fail_timeout=10s"
      - "angie.http.upstreams.u.backup=true"
```

<a id="docker-labels"></a>

## 标签

标签在代理服务器组中指定服务器参数，类似于 `server` 指令的参数：

| 标签                                                         | 用途                                      |
|------------------------------------------------------------|-----------------------------------------|
| `angie.(http|stream).upstreams.<name>.port=<port>`  *（必需）* | Angie 将连接到的容器端口；容器本身被添加到名为 `<name>` 的组。 |
| `angie.network=<docker-network>`                           | 用于获取容器 IP 地址的 Docker 网络名称。              |
| `angie.(http|stream).upstreams.<name>.weight=<n>`          | `weight` 参数的值。                          |
| `angie.(http|stream).upstreams.<name>.max_conns=<n>`       | 最大并发连接数（`max_conns`）。                   |
| `angie.(http|stream).upstreams.<name>.max_fails=<n>`       | 失败尝试阈值（`max_fails`）。                    |
| `angie.(http|stream).upstreams.<name>.fail_timeout=<t>`    | 计算失败尝试的时间间隔（`fail_timeout`）。            |
| `angie.(http|stream).upstreams.<name>.backup=true|false`   | 将服务器标记为 `backup`。                       |
| `angie.(http|stream).upstreams.<name>.sid=<string>`        | 为代理服务器设置自定义服务器标识符（`sid`）。               |
| `angie.(http|stream).upstreams.<name>.slow_start=<time>`   | 启用具有可配置时间段的 `slow_start` 模式。            |

<a id="directives-13"></a>

## 指令

<a id="index-0"></a>

<a id="docker-endpoint"></a>

### docker_endpoint

| [语法](https://cn.angie.software//angie/docs/configuration/configfile.md#configfile)   | `docker_endpoint` `URL`;   |
|--------------------------------------------------------------------------------------|----------------------------|
| 默认值                                                                                  | —                          |
| [上下文](https://cn.angie.software//angie/docs/configuration/configfile.md#configfile)  | http                       |

指定连接到 Docker 守护进程的方法并启用容器事件跟踪。
支持以下选项：

| `unix:/var/run/docker.sock`            | 通过 Unix 套接字连接（例如 `/var/run/docker.sock`）。   |
|----------------------------------------|---------------------------------------------|
| `http://host:port`、`https://host:port` | 通过 HTTP 或 HTTPS 连接到远程 Docker API。           |

可以使用 [client](https://cn.angie.software//angie/docs/configuration/modules/http/index.md#client) 上下文进一步配置连接，该模块在其中添加了两个命名的 `location` 块：

- `@docker_events` 用于接收容器事件；
- `@docker_containers` — 用于获取容器信息。

默认情况下，它们包含带有连接地址的 [proxy_pass](https://cn.angie.software//angie/docs/configuration/modules/http/http_proxy.md#proxy-pass) 指令以及其他几个最佳默认设置，可以向其中添加 [代理](https://cn.angie.software//angie/docs/configuration/modules/http/http_proxy.md#http-proxy) 模块的其他设置。

如果指定了该指令，Angie 将使用指定的方法打开到 Docker 的连接，请求正在运行的容器列表，分析它们的标签并处理所有后续容器事件，根据标签在代理服务器组中添加或删除服务器。

<a id="index-1"></a>

<a id="docker-max-object-size"></a>

### docker_max_object_size

| [语法](https://cn.angie.software//angie/docs/configuration/configfile.md#configfile)   | `docker_max_object_size` `<size>`;   |
|--------------------------------------------------------------------------------------|--------------------------------------|
| 默认值                                                                                  | `64k`                                |
| [上下文](https://cn.angie.software//angie/docs/configuration/configfile.md#configfile)  | http                                 |

设置用于 Docker 请求的 JSON 响应和容器事件流的最大缓冲区大小。

- 对于常规请求（API 版本、容器列表、容器信息）：整个响应必须适合缓冲区，否则会发生错误。
- 对于容器事件，使用流式处理并重用缓冲区，这允许处理无限的事件流。

典型值 `64k` 足以容纳大约 25 个容器。

当发生 Docker API 连接错误或响应处理错误时，该模块会在特定时间间隔自动重试。
获取特定容器信息的最大重试次数限制为两次  *额外* 尝试；之后，该模块将停止对该容器的尝试。
