1. 概述

我们都知道Docker的流行程度,以及它对于Java开发者将Spring Boot应用容器化的重要性。然而,如何在Docker化的Spring Boot应用中设置环境变量可能对一些开发者来说是个问题。

在这篇教程中,我们将解释如何在Docker容器中的Spring Boot应用中启动带有配置项的实例。

2. 基本Dockerfile

通常,将Spring Boot应用Docker化,我们只需提供一个Dockerfile

让我们看看我们Spring Boot应用的最小Dockerfile示例:

FROM openjdk:17-jdk-alpine
COPY target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

当然,我们可以使用docker build构建我们的Docker镜像:

docker build --tag=docker-with-spring-profile:latest .

这样,我们就可以通过镜像docker-with-spring-profile运行我们的应用:

docker run docker-with-spring-profile:latest

如我们所见,我们的Spring Boot应用以"default"配置启动:

2024-02-29 22:34:25.268 INFO 1 --- [main] c.b.docker.spring.DemoApplication: Starting DemoApplication using Java 17-ea with PID 1 (/app.jar started by root in /)
2024-02-29 22:34:25.270 INFO 1 --- [main] c.b.docker.spring.DemoApplication: No active profile set, falling back to 1 default profile: "default"
//...

3. 在Dockerfile中设置配置项

为我们的Docker化应用设置配置项的一种方法是使用Spring Boot的命令行参数"-Dspring.profiles.active"

因此,为了设置配置项为"test",我们需要在DockerfileENTRYPOINT行中添加新的参数"-Dspring.profiles.active=test"

//...
ENTRYPOINT ["java", "-Dspring.profiles.active=test", "-jar", "/app.jar"]

为了观察配置项的变化,我们再次使用相同的命令运行容器:

docker run docker-with-spring-profile:latest

相应地,我们可以看到"test"配置被成功应用于我们的应用:

2024-02-29 22:39:33.210 INFO 1 --- [main] c.b.docker.spring.DemoApplication: Starting DemoApplication using Java 17-ea with PID 1 (/app.jar started by root in /)
2024-02-29 22:39:33.212 INFO 1 --- [main] c.b.docker.spring.DemoApplication: The following 1 profile is active: "test"
//...

4. 使用环境变量设置配置项

有时,在Dockerfile中硬编码配置项并不方便。如果我们需要多个配置,每次运行容器时选择其中一个可能会变得繁琐。

然而,有一个更好的选择。在启动时,Spring Boot会查找一个特殊的环境变量SPRING_PROFILES_ACTIVE

因此,实际上,我们可以利用docker run命令在启动时设置Spring配置项:

docker run -e "SPRING_PROFILES_ACTIVE=test" docker-with-spring-profile:latest

此外,根据我们的应用场景,我们可以通过逗号分隔的字符串一次设置多个配置项:

docker run -e "SPRING_PROFILES_ACTIVE=test1,test2,test3" docker-with-spring-profile:latest

但是,需要注意的是Spring Boot有特定的属性优先级顺序命令行参数优于环境变量。因此,为了让SPRING_PROFILES_ACTIVE工作,我们需要撤销我们的Dockerfile

结果,我们从DockerfileENTRYPOINT行中移除"-Dspring.profiles.active=test"参数:

//...
ENTRYPOINT ["java", "-jar", "/app.jar"]

最后,我们可以看到通过SPRING_PROFILES_ACTIVE设置的配置项被考虑在内:

2024-02-29 22:50:28.924 INFO 1 --- [main] c.b.docker.spring.DemoApplication: Starting DemoApplication using Java 17-ea with PID 1 (/app.jar started by root in /)
2024-02-29T22:50:28.926562249Z 2022-04-22 22:50:28.926 INFO 1 --- [main] c.b.docker.spring.DemoApplication: The following 3 profiles are active: "test1", "test2", "test3"
//..

5. 在Docker Compose文件中设置配置项

作为另一种方法,我们也可以在docker-compose文件中提供环境变量

此外,为了更好地利用docker run操作,我们可以为每个配置创建一个docker-compose文件。

让我们为"test"配置创建一个docker-compose-test.yml文件:

version: "3.5"
services:
  docker-with-spring-profile:
    image: docker-with-spring-profile:latest
    environment:
      - "SPRING_PROFILES_ACTIVE=test"

同样,我们为"prod"配置创建另一个文件docker-compose-prod.yml——第二个文件的区别在于第二个文件中包含"prod"配置:

//...
environment:
  - "SPRING_PROFILES_ACTIVE=prod"

因此,我们可以通过两个不同的docker-compose文件运行我们的容器:

# for the profile 'test'
docker-compose -f docker-compose-test.yml up

# for the profile 'prod'
docker-compose -f docker-compose-prod.yml up

6. 总结

在这篇教程中,我们描述了在Docker化的Spring Boot应用中设置配置项的不同方法,并展示了使用Docker和Docker Compose的一些示例。

一如既往,本文中的所有代码示例都可在GitHub上找到。