在 Docker 中设置 Spring Boot Profile

1、简介

在容器化大行其道的今天,越来越多人选择把 Spring Boot 应用部署到 Docker 中。

本文将带你了解在 Docker 容器中启动 Spring Boot 应用时,如何设置其 Profile。

2、基本的 Dockerfile

一般来说,要容器化 Spring Boot 应用,只需提供一个 Dockerfile

Spring Boot 应用的最小 Dockerfile,如下:

FROM openjdk:11
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” Profile 启动:

2022-04-22 22:34:25.268 INFO 1 --- [main] c.b.docker.spring.DemoApplication: Starting DemoApplication using Java 11.0.14.1 on ea8851bea75f with PID 1 (/app.jar started by root in /)
2022-04-22 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 中设置 Profile

设置 Profile 的一种方法是使用 Spring Boot 的命令行参数:-Dspring.profiles.active

DockerfileENTRYPOINT 行中添加了一个新参数 -Dspring.profiles.active=test",将 Profile 设置为 test

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

使用相同命令,再次运行容器:

docker run docker-with-spring-profile:latest

如你所见,Profile 为 test,设置生效:

2022-04-22 22:39:33.210 INFO 1 --- [main] c.b.docker.spring.DemoApplication: Starting DemoApplication using Java 11.0.14.1 on 227974fa84b2 with PID 1 (/app.jar started by root in /)
2022-04-22 22:39:33.212 INFO 1 --- [main] c.b.docker.spring.DemoApplication: The following 1 profile is active: "test"
//...

4、通过环境变量设置 Profile

Dockerfile 中使用硬编码的 Profile 并不灵活。如果我们有多个 Profile,在运行容器时需要选择其中一个,这就很麻烦。

有一个更好的方式,Spring Boot 在启动过程中会查找一个特殊的环境变量 SPRING_PROFILES_ACTIVE

因此,我们可以利用 docker run 命令在启动时设置 Spring Profile:

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

而且,还可以一次设置多个 Profile,通过逗号分隔:

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 变量设置的 Profile 已经生效:

2022-04-22 22:50:28.924 INFO 1 --- [main] c.b.docker.spring.DemoApplication: Starting DemoApplication using Java 11.0.14.1 on 18eacb6362f8 with PID 1 (/app.jar started by root in /)
2022-04-22T22: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 文件中设置 Profile

另一种方法是在 docker-compose 文件中提供环境变量。

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

test Profile 创建一个 docker-compose-test.yml 文件:

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

同样,为 prod Profile 创建另一个文件 docker-compose-prod.yml,唯一不同的是第二个文件中的 Profileprod

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

现在,可以通过两个不同的 docker-compose 文件来运行容器:

# 'test' Profile 
docker-compose -f docker-compose-test.yml up

# 'prod' Profile
docker-compose -f docker-compose-prod.yml up

6、总结

本文介绍了在以 docker 容器运行的 Spring Boot 应用中设置 Profile 的不同方法,并展示了使用 Docker 和 Docker Compose 的一些示例。


参考:https://www.baeldung.com/spring-boot-docker-start-with-profile