# 7.10. Docker Compose 支持

Docker Compose 是一种流行的技术，可用于定义和管理应用程序所需服务的多个容器。通常会在应用程序旁边创建一个`compose.yml`文件，用于定义和配置服务容器。

Docker Compose 的典型工作流程是运行`docker compose up`，处理您的应用程序并连接到已启动的服务，然后在完成后运行`docker compose down`。

`spring-boot-docker-compose`模块可以包含在项目中，为使用 Docker Compose 处理容器提供支持。将模块依赖项添加到您的构建中，如以下 Maven 和 Gradle 清单所示：

Maven

```
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-docker-compose</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
```

Gradle

```
dependencies {
    developmentOnly("org.springframework.boot:spring-boot-docker-compose")
}
```

> `docker-compose`或`docker compose` CLI 应用程序需要位于您的路径上，以便 Spring Boot 的支持正常工作 。

当此模块作为依赖项包含时，Spring Boot 将执行以下操作：

* 在应用程序目录中搜索`compose.yml`和其他常见的撰写文件名
* 使用找到的`compose.yml`调用`docker compose up`
* 为每个受支持的容器创建服务连接 Bean
* 当应用程序关闭时调用`docker compose stop`

如果启动应用程序时 Docker Compose 服务已经在运行，Spring Boot 将仅为每个支持的容器创建服务连接 Bean。它不会再次调用`docker compose up`，并且当应用程序关闭时也不会调用`docker compose stop`。

> 默认情况下，Spring Boot 的 Docker Compose 支持在运行测试时处于禁用状态。要启用它，请设置`spring.docker.compose.skip.in-tests`为`false`。

**7.10.1. 服务连接**

服务连接是与任何远程服务的连接。Spring Boot 的自动配置可以使用服务连接的详细信息，并使用它们来建立与远程服务的连接。执行此操作时，连接详细信息优先于任何与连接相关的配置属性。

当使用 Spring Boot 的 Docker Compose 支持时，服务连接将建立到容器映射的端口。

> Docker compose 通常的使用方式是将容器内的端口映射到计算机上的临时端口。例如，Postgres 服务器可能使用端口 5432 在容器内运行，但在本地映射到完全不同的端口。服务连接将始终发现并使用本地映射的端口。

通过容器的镜像名称建立服务连接。目前支持以下服务连接：

| 连接详情                             | 匹配于                                                                                      |
| -------------------------------- | ---------------------------------------------------------------------------------------- |
| `ActiveMQConnectionDetails`      | 名为“symptoma/activemq”的容器                                                                 |
| `CassandraConnectionDetails`     | 名为“cassandra”的容器                                                                         |
| `ElasticsearchConnectionDetails` | 名为“elasticsearch”的容器                                                                     |
| `JdbcConnectionDetails`          | 名为“gvenzl/oracle-free”、“gvenzl/oracle-xe”、“mariadb”、“mssql/server”、“mysql”或“postgres”的容器 |
| `MongoConnectionDetails`         | 名为“mongo”的容器                                                                             |
| `Neo4jConnectionDetails`         | 名为“neo4j”的容器                                                                             |
| `OtlpMetricsConnectionDetails`   | 名为“otel/opentelemetry-collector-contrib”的容器                                              |
| `OtlpTracingConnectionDetails`   | 名为“otel/opentelemetry-collector-contrib”的容器                                              |
| `PulsarConnectionDetails`        | 名为“apachepulsar/pulsar”的容器                                                               |
| `R2dbcConnectionDetails`         | 名为“gvenzl/oracle-free”、“gvenzl/oracle-xe”、“mariadb”、“mssql/server”、“mysql”或“postgres”的容器 |
| `RabbitConnectionDetails`        | 名为“rabbitmq”的容器                                                                          |
| `RedisConnectionDetails`         | 名为“redis”的容器                                                                             |
| `ZipkinConnectionDetails`        | 名为“openzipkin/zipkin”的容器。                                                                |

**7.10.2. 自定义镜像**

有时您可能需要使用您自己的镜像版本来提供服务。您可以使用任何自定义镜像，只要其行为方式与标准镜像相同即可。具体来说，标准映像支持的任何环境变量也必须在您的自定义映像中使用。

如果您的映像使用不同的名称，您可以在`compose.yml`文件中使用标签，以便 Spring Boot 可以提供服务连接。使用名为的标签`org.springframework.boot.service-connection`来提供服务名称。

例如:

```
services:
  redis:
    image: 'mycompany/mycustomredis:7.0'
    ports:
      - '6379'
    labels:
      org.springframework.boot.service-connection: redis
```

**7.10.3. 跳过特定容器**

如果您的`compose.yml`定义了一个容器映像，并且不想连接到您的应用程序，则可以使用标签来忽略它。任何带有`org.springframework.boot.ignore` 标签的容器都会被 Spring Boot 忽略。

例如：

```
services:
  redis:
    image: 'redis:7.0'
    ports:
      - '6379'
    labels:
      org.springframework.boot.ignore: true
```

**7.10.4. 使用特定的撰写文件**

如果您的撰写文件与应用程序不在同一目录中，或者名称不同，则可以在您的`application.yaml` 中使用`application.properties`或`spring.docker.compose.file`来指向不同的文件。属性可以定义为精确路径或与应用程序相关的路径。

例如：

```
spring.docker.compose.file=../my-compose.yml
```

**7.10.5. 等待容器准备就绪**

由 Docker Compose 启动的容器可能需要一些时间才能完全准备好。检查准备情况的建议方法是在`compose.yml`文件中的服务定义下添加一个`healthcheck`部分。

由于从`compose.yml`文件中省略`healthcheck`配置的情况并不少见，因此 Spring Boot 还会直接检查服务准备情况。默认情况下，当可以建立到容器映射端口的 TCP/IP 连接时，容器被视为准备就绪。

您可以通过在`compose.yml`文件中添加`org.springframework.boot.readiness-check.tcp.disable`标签来针对每个容器禁用此功能。

例如：

```
services:
  redis:
    image: 'redis:7.0'
    ports:
      - '6379'
    labels:
      org.springframework.boot.readiness-check.tcp.disable: true
```

您还可以更改`application.properties`或`application.yaml`文件中的超时值：

```
spring.docker.compose.readiness.tcp.connect-timeout=10s
spring.docker.compose.readiness.tcp.read-timeout=5s
```

总体超时可以使用`spring.docker.compose.readiness.timeout`配置。

**7.10.6. 控制 Docker Compose 生命周期**

默认情况下，Spring Boot在应用程序启动调用`docker compose up`和关闭时调用`docker compose stop`。如果您希望有不同的生命周期管理，您可以使用`spring.docker.compose.lifecycle-management`属性。

支持以下值：

* `none`- 不要启动或停止 Docker Compose
* `start-only`- 在应用程序启动时启动 Docker Compose 并使其保持运行
* `start-and-stop`- 当应用程序启动时启动 Docker Compose，并在 JVM 退出时停止它

此外，您可以使用`spring.docker.compose.start.command`属性来更改是否使用`docker compose up`或`docker compose start`。`spring.docker.compose.stop.command`允许您配置是否使用`docker compose down`或`docker compose stop`。

以下示例显示了如何配置生命周期管理：

```
spring.docker.compose.lifecycle-management=start-and-stop
spring.docker.compose.start.command=start
spring.docker.compose.stop.command=down
spring.docker.compose.stop.timeout=1m
```

**7.10.7. 激活 Docker Compose 配置文件**

Docker Compose 配置文件与 Spring 配置文件类似，它们允许您针对特定环境调整 Docker Compose 配置。如果您想激活特定的 Docker Compose 配置文件，您可以使用您的`application.properties`或`application.yaml`文件中的`spring.docker.compose.profiles.active`属性：

```
spring.docker.compose.profiles.active=myprofile
```
