Unable to run docker jars in production in Java 11

I’ve been getting my little application ready to run in production, and after some hiccups, I’ve just been hitting a brick wall around booting up any service. Basically put, even copying the shopping-cart-java example, I’m just having issues where Guice comes up with an injection error for ServiceInfo not being constructable.

This does feel awkwardly similar to Guice unable to create injector, but I can assure you that the difference here being that this is now Java 11, it “runs fine” in development, but arriving at this miserable log that’s near useless leads me to believe there’s a fundamental problem with Guice injections for production with regards to the jar ordering for the classpath of the docker images.

Even now running with the app in development through IDE, these things work fine, but the moment I try to spin these up in a Docker environment, it feels as though the ordering of modules is just chaotically defined by the host os, leading to this sort of error.

Any advice on proceeding? I’m fairly confident in the problem, but short of manual dependency listing in a specific order, I’m not sure what to do next…

I ended up having to find out that there’s a problem with running the container image, and ended up ditching the maven route and built using sbt to have some better assurance of precise dependency class path listing (instead of leaving all the jars in a specific folder).

Ended up applying several attempts at fixing the problem, not quite sure which fix exactly resolved it, but amongst several, I’ve done the following:

  • Switch to using sbt-native-packager
    • Attempting to customize the docker image any further and extracting the dependency jars to specify an exact class path was a nightmare with maven
  • Generate production specific configurations using Terraform deployments:
    • Allowed for variable/string interpolation for deployment, given some services may not be aware of specifics for infrastructure related items
    • Reduce the amount of environment injected variables
    • Storing the production config as a Kubernetes mounted secret
  • Specify LagomService → Kubernetes Service name mappings

I’m not confident in other changes I’ve made to make my services deployable in a Kubernetes environment, but I can definitely say that since switching to the sbt-native-packager route, things have been much easier to reason about than with the maven route.

For reference: