Proxy core native image build optimization
jroper opened this issue · 3 comments
The three docker images built from the proxy core project (no-store, in-memory and dev-mode) are identical apart from the command that gets executed. Yet, when we build them now, the native image gets recompiled. Docker does support incremental builds, it will only re-execute a build stage if the files have changed. The files that are changing are the jars we produce - the contents of the jars are identical but the timestamps of the files in them are different, which changes the jar files. I haven't worked out which timestamps are different and/or why incremental building isn't working for the jar files.
It would be ideal if this didn't happened. There are three possible solutions that I see:
- Ensure the jars don't get rebuilt when no source files have changed. There was a point when I had this working. This is the most natural in some ways because the idea is that a full build always gets done with incremental optimisations applied. However, it's very fragile, add a new sbt plugin, or just tiny sbt changes can break it.
- Use a different zip implementation that zeros all the timestamps to build jars. This is more stable, though still has some fragility, since there are other reasons the files could change (generate sources including timestamps for example).
- Build a base docker image for the proxy core project, and then have separate Dockerfiles that use this image as the starting point. This is guaranteed to work, is not fragile, however, it does mean building these docker images is a two step process, first you need to build the core image, then build the next image. And you can't use the sbt dependency tree to do this, because it will just end up reexecuting the build of the base image each time.
I'm not sure which is the best option.
We could look at using https://github.com/raboof/sbt-reproducible-builds, which will strip the timestamps from jars.
Also wonder if it's worthwhile going even further and seeing what it would be like to have one native image which has all the persistence backends and can be switched into different modes.
Would just need to consider image sizes for that. And yeah we don't necessarily need different images, we could switch entirely using config.
But certainly, for the core build, we could switch to specifying the mode using arguments passed via Kubernetes, rather than in Docker. I think that might be simpler than our current setup.