The spring-boot:build-image Maven goal and bootBuildImage Gradle task configure the CNB builder to cache layers created by buildpacks to make subsequent image builds run faster. Currently the cache is stored as named volume in the Docker daemon. This doesn't work well when running builds on CI/CD environments, since Docker daemons might be ephemeral or builds might run on different worker nodes.

To better support running builds on CI/CD environments, the CNB builder supports storing cached layers in an OCI image. The Boot plugins could be enhanced to support this configuration also.

For Maven, the build configuration would be:

<project>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <image>
            <buildCache>
              <image>
                <name>repo.example.com/cache-${project.artifactId}:latest</name>
              </image>
            </buildCache>
          </image>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

For Gradle, the build configuration would be:

bootBuildImage {
  buildCache {
    image {
      name = "repo.example.com/cache-${rootProject.name}:latest"
    }
  }
}

Note: the image option is not available for the launch cache, only for the build cache.

Comment From: davidecavestro

It would be amazing to have cache image auto-pull, or an option to control whether the pull should be forced.

Comment From: nbokdam

During an innovation day I gave this a shot, but didn't succeed: https://github.com/nbokdam/spring-boot/tree/feature/add-build-cache-image

I'm most likely not going to finish this, but wanted to share my findings here.

Logging of my test project:

[INFO] --- spring-boot:3.2.0-nbokdam-SNAPSHOT:build-image (default-cli) @ sb-test-build-image ---
[INFO] Building image 'docker.io/library/sb-test-build-image:0.0.1-SNAPSHOT'
[INFO] 
[INFO]  > Pulling builder image 'docker.io/paketobuildpacks/builder-jammy-base:latest' 100%
[INFO]  > Pulled builder image 'paketobuildpacks/builder-jammy-base@sha256:9688a1421ac4c582925778465f6bb7c5aeecde564dfc6cd80debdbf193cf07ff'
[INFO]  > Pulling run image 'docker.io/paketobuildpacks/run-jammy-base:latest' 100%
[INFO]  > Pulled run image 'paketobuildpacks/run-jammy-base@sha256:e817bca35911221677b678bf8bf29a18c17ce867b29bd9d0b0c3342c063854e5'
[INFO]  > Executing lifecycle version v0.18.1
[INFO]  > Using build cache image 'docker.io/nbokdam/sb-cace'
[INFO] 
[INFO]  > Running creator
[INFO]     [creator]     ===> ANALYZING
[INFO]     [creator]     ERROR: failed to initialize analyzer: validating registry write access: ensure registry read/write access to nbokdam/sb-cace:latest

My conclusion there was, that the creator somehow needs to be authenticated in order to push to the registry. However, I didn't see an obvious way to do that. It was not a simple matter of logging in my local docker daemon.

Good luck to a future implementer!

Comment From: scottfrederick

Thanks for working at this @nbokdam. What you have looks like a good start for the Maven side of this enhancement. I'll find some time to take a closer look and see what else needs to be done.