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.yml in src/main/resources/ with only the app name in it.
spring:
  application:
    name: demo
  • application-local.yml in src/main/resources/ with the profile for docker composer in it.
spring:
  docker:
    compose:
      profiles:
        active: "local"
  • compose-local.yaml in 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.