Use case
Run spring-boot app with an active profile, for this case local, using of reference this: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.docker-compose.profiles, having the following:
application.ymlinsrc/main/resources/with only the app name in it.
spring:
application:
name: demo
application-local.ymlinsrc/main/resources/with the profile for docker composer in it.
spring:
docker:
compose:
profiles:
active: "local"
compose-local.yamlin the root directory with the a postgresql database as example:
services:
postgres:
image: 'postgres:latest'
environment:
- 'POSTGRES_DB=mydatabase'
- 'POSTGRES_PASSWORD=secret'
- 'POSTGRES_USER=myuser'
ports:
- '5432'
Expected behavior:
Find the file following this pattern:
- compose
-active-profile.yaml - compose
-active-profile.yml - docker-compose
-active-profile.yaml - docker-compose
-active-profile.yml
Current behavior:
The spring boot app is ignoring the profile if not defined in spring.docker.compose.file property, looking for:
- compose.yaml
- compose.yml
- docker-compose.yaml
- docker-compose.yml
And because none of those files are defined and the ./compose-local.yaml is not defined explicitly in spring.docker.compose.file its fails with:
java.lang.IllegalStateException: No Docker Compose file found in directory '/.'
The problem with this its in this 2 files of the library:
org.springframework.boot.docker.compose.lifecycle.DockerComposeLifecycleManager.java#L109
This try to get the default file always with:
DockerComposeFile composeFile = getComposeFile();
And this method will fail with Assert.state(composeFile != null, () -> "No Docker Compose file found in directory '%s'"
Because this method ignore the active profile:
org.springframework.boot.docker.compose.core.DockerComposeFile.java#L89
public static DockerComposeFile find(File workingDirectory) {
File base = (workingDirectory != null) ? workingDirectory : new File(".");
if (!base.exists()) {
return null;
}
Assert.isTrue(base.isDirectory(), () -> "'%s' is not a directory".formatted(base));
Path basePath = base.toPath();
for (String candidate : SEARCH_ORDER) {
Path resolved = basePath.resolve(candidate);
if (Files.exists(resolved)) {
return of(resolved.toAbsolutePath().toFile());
}
}
return null;
}
The SEARCH_ORDER only considers:
private static final List<String> SEARCH_ORDER = List.of("compose.yaml", "compose.yml", "docker-compose.yaml", "docker-compose.yml");
As you can see, no profiles in any place.
This is a link with an example project if you want to replicate: vcruzmj/bug-docker-composer-springboot
Comment From: wilkinsona
Docker Compose profiles and Spring profiles are separate concepts. When using a Docker Compose profile, the name of the file does not change. Instead, services are assigned to a particular profile within the compose.yaml or compose.yml file. Please see https://docs.docker.com/compose/profiles/ to learn more about Docker Compose profiles.
Comment From: vcruzmj
Thanks, I misunderstood the documentation and mix it with this article https://howtodoinjava.com/spring-boot/spring-boot-docker-compose/. I fully understand this now.