Spring Boot 与 Docker
观察 GraphQL 的实际运行

本指南将引导您使用 Spring Cloud Vault 构建一个从 HashiCorp Vault 获取配置属性的应用程序。

你将构建什么

您将启动 Vault,将配置属性存储在 Vault 中,构建一个 Spring 应用程序并将其与 Vault 连接。

所需内容

  • 大约15分钟

  • 一个喜欢的文本编辑器或IDE

  • Java 17 或更高版本

如何完成本指南

与大多数 Spring 入门指南 一样,您可以从头开始完成每个步骤,也可以直接查看 此仓库 中的代码跳到解决方案部分。

要在本地环境中查看最终结果,您可以执行以下操作之一:

从 Spring Initializr 开始

您可以使用这个预先初始化的项目,然后点击生成以下载一个ZIP文件。该项目已配置为适合本教程中的示例。

要手动初始化项目:

  1. 访问 https://start.spring.io。该服务会拉取应用程序所需的所有依赖项,并为您完成大部分设置工作。

  2. 选择 Gradle 或 Maven 以及您想要使用的语言。本指南假设您选择了 Java。

  3. 点击 Dependencies 并选择 Vault Configuration

  4. 点击 Generate

  5. 下载生成的 ZIP 文件,该文件是一个根据您的选择配置好的应用程序的压缩包。

如果您的 IDE 集成了 Spring Initializr,您可以直接在 IDE 中完成这个过程。

运行 HashiCorp Vault

完成本指南需要一个 HashiCorp Vault 实例。本指南使用 Docker Compose 来运行容器化的 HashiCorp Vault。已提供一个 compose.yaml 文件:

services:
  vault:
    container_name: "guide-vault"
    image: hashicorp/vault:latest
    environment:
      VAULT_DEV_ROOT_TOKEN_ID: "00000000-0000-0000-0000-000000000000"
    ports:
      * "8200:8200"

使用 docker compose up 命令运行 HashiCorp Vault 容器。

在 Vault 中存储配置

Vault 是一个秘钥管理系统,允许您存储敏感数据,这些数据在静态时是加密的。您需要访问 Vault 容器来存储数据。使用以下命令连接到正在运行的 Docker 容器:

docker exec -it guide-vault sh

您现在正在 HashiCorp Vault 容器内运行命令。首先,您需要设置两个环境变量,以便将 Vault CLI 指向 Vault 端点并提供身份验证令牌。

export VAULT_TOKEN="00000000-0000-0000-0000-000000000000"
export VAULT_ADDR="http://127.0.0.1:8200"

现在您可以将配置键值对存储在Vault中。在本指南中,您将存储两个键值对:

vault kv put secret/gs-vault-config example.username=demouser example.password=demopassword
vault kv put secret/gs-vault-config/cloud example.username=clouduser example.password=cloudpassword

现在您已经在 Vault 中写入了两个条目:secret/gs-vault-configsecret/gs-vault-config/cloud

Vault 容器正在运行且数据已加载,您现在可以将注意力转向 Spring 应用程序了。

定义您的配置类

为您的 Spring 应用程序创建一个简单的配置:

src/main/java/hello/MyConfiguration.java

package hello;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @author Mark Paluch
 */
@ConfigurationProperties("example")
public class MyConfiguration {

  private String username;

  private String password;

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }
}

配置您的应用程序

在这里,您可以使用 application.properties 配置您的应用程序。下面的代码使用了 Spring Boot 的 Config Data API,允许从 Vault 导入配置。

src/main/resources/application.properties

spring.application.name=gs-vault-config
spring.cloud.vault.token=00000000-0000-0000-0000-000000000000
spring.cloud.vault.scheme=http
spring.cloud.vault.kv.enabled=true
spring.config.import:  vault://

创建一个应用程序类

在这里您创建了一个包含所有组件的 Application 类。

src/main/java/hello/Application.java

package hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties(MyConfiguration.class)
public class Application implements CommandLineRunner {

  private final MyConfiguration configuration;

  public Application(MyConfiguration configuration) {
    this.configuration = configuration;
  }

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

  @Override
  public void run(String... args) {

    Logger logger = LoggerFactory.getLogger(Application.class);

    logger.info("----------------------------------------");
    logger.info("Configuration properties");
    logger.info("   example.username is {}", configuration.getUsername());
    logger.info("   example.password is {}", configuration.getPassword());
    logger.info("----------------------------------------");
  }
}

Spring Cloud Vault 使用 VaultOperations 与 Vault 进行交互。来自 Vault 的属性会被映射到 MyConfiguration,以实现类型安全的访问。@EnableConfigurationProperties(MyConfiguration.class) 启用了配置属性映射,并注册了一个 MyConfiguration bean。

Application 包含一个 main() 方法,该方法会自动装配一个 MyConfiguration 实例。

运行应用程序

您可以通过 IDE 运行主方法。或者,使用 ./gradlew bootRun./mvnw spring-boot:run 命令启动应用程序。

由于我们的 Application 实现了 CommandLineRunnerrun 方法会在启动时自动调用。您应该会看到以下输出:

*---------------------------------------
Configuration properties
        example.username is demouser
        example.password is demopassword
*---------------------------------------

现在使用 cloud 配置文件启动应用程序。您可以在 Gradle 中使用 ./gradlew bootRun --args='--spring.profiles.active=cloud' 命令,或者在 Maven 中使用 ./mvnw spring-boot:run -Dspring-boot.run.arguments="--spring.profiles.active=cloud" 命令来执行此操作。当您使用 cloud 配置文件运行应用程序时,您会看到:

*---------------------------------------
Configuration properties
        example.username is clouduser
        example.password is cloudpassword
*---------------------------------------

配置属性会根据激活的配置文件进行绑定。Spring Cloud Vault 会从 spring.application.name(即 gs-vault)构造一个 Vault 上下文路径,并附加配置文件名称(cloud),因此启用 cloud 配置文件时,会从 secret/gs-vault-config/cloud 额外获取配置属性。

构建应用程序

本节描述运行本指南的不同方式:

  1. 构建并执行 JAR 文件

  2. 使用 Cloud Native Buildpacks 构建并执行 Docker 容器

  3. 构建并执行原生镜像

  4. 使用 Cloud Native Buildpacks 构建并执行原生镜像容器

无论您选择如何运行应用程序,输出结果都应该是相同的。

要运行应用程序,您可以将应用程序打包为可执行的 jar 文件。./mvnw clean package 命令将应用程序编译为可执行的 jar 文件。然后,您可以使用 java -jar target/gs-vault-config-0.0.1-SNAPSHOT.jar 命令来运行该 jar 文件。

或者,如果您有可用的 Docker 环境,您可以直接使用 buildpacks 从 Maven 或 Gradle 插件创建 Docker 镜像。使用 Cloud Native Buildpacks,您可以创建可在任何地方运行的 Docker 兼容镜像。Spring Boot 直接支持 Maven 和 Gradle 的 buildpack。这意味着您只需输入一个命令,就可以快速将合理的镜像放入本地运行的 Docker 守护进程中。要使用 Cloud Native Buildpacks 创建 Docker 镜像,请运行 ./mvnw spring-boot:build-image 命令。在启用 Docker 环境的情况下,您可以使用 docker run --network container:guide-vault docker.io/library/gs-vault-config:0.0.1-SNAPSHOT 命令来运行应用程序。

--network 标志告诉 Docker 将我们的指南容器附加到外部容器正在使用的现有网络。您可以在 Docker 文档 中找到更多信息。

原生镜像支持

Spring Boot 还支持编译为原生镜像,前提是您的机器上安装了 GraalVM 发行版。

然后,您可以运行 ./mvnw -Pnative native:compile 命令来生成原生镜像。构建完成后,通过执行 target/gs-vault-config 命令,您将能够以近乎瞬时的启动时间运行代码。

要使用 Maven 创建原生镜像容器,您应确保 pom.xml 文件使用了 spring-boot-starter-parentorg.graalvm.buildtools:native-maven-plugin。该插件应位于 <build> <plugins> 部分中:

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
</plugin>

您还可以使用 Buildpacks 创建原生镜像。通过运行 ./mvnw -Pnative spring-boot:build-image 命令,您可以生成一个原生镜像。构建完成后,您可以使用 docker run --network container:guide-vault docker.io/library/gs-vault-config:0.0.1-SNAPSHOT 命令启动您的应用程序。

总结

恭喜!您已经成功设置了一个 Vault 服务器,并编写了一个简单的应用程序,该程序使用 Spring Vault 将机密信息读取到配置属性中,并使用强大的加密算法对数据进行加密——这一切都无需费心实现密钥管理、加密模式和填充。

本页目录