Closed jstrachan closed 6 years ago
if we go the maven plugin route am thinking the logic could be something like the following to find the jar to use:
draft.app.jar = foo-${project-version}.jar
target/*.jar
then use that${project.build.finalName}.jar
if that existsThen once the jar is found, copy it to target/app.jar
.
A more optimal approach might be to generate a text file at target/app-jar-name.txt
and use that as the file name to copy into the resulting docker image? Then it saves copying 10-40mb of jar in java in each build?
Maybe to avoid running the mvn plugin on each build, we could just run it once every now and again (or as soon as the user runs draft create
for the first time on the source code) and then use the above plugin logic to deduce the jar file but generate a file at src/main/resources/draft-app-jar-name.txt
which could contain the text like ${project.build.finalName}.jar
or whatever.
Then the Dockerfile
could load the file name from target/classes/draft-app-jar-name.txt
expanded via the maven build with any version / artefact id etc?
At least then we don't incur the cost of the mvn plugin on each build (or folks could run it on each build or not). Though one issue with this approach could be that the pom.xml
disables filtering on src/main/resources
; so we may need to store it in src/main/draft-resources
and add an explicit <build><resources>
section for this folder as part of draft create
?
I'm kinda liking the approach that the mvn build should generate a canonical file at a canonical place that includes the jar file name to use for the app; as we can then try push this capability down into many plugins over time. (e.g. spring boot maven plugin maybe?)
Hi James,
I've bumped into this via twitter... to specify your final build name as a maven command line argument, please see here: https://stackoverflow.com/questions/13876165/how-to-override-maven-property-in-command-line
Btw, I don't imply that this is the best solution to the jar name problem in docker file.
@diginoise thanks for the feedback - yeah I spotted that too; though it requires tweaks to the pom.xml to use a property so you can pass it in on the CLI; then assumes folks are using plugins correctly to respect the finalName property too; so it feels a little vague. It can certainly work for 1 project; but it doesn't feel right to work on any maven project
closed via #590
the current
Dockerfile
hard codes the jar file generated by the maven build tohelloworld-jar-with-dependencies.jar
https://github.com/Azure/draft/blob/master/packs/java/Dockerfile#L9which is great for the example but isn't gonna work for many other java projects out there (that are not called 'helloworld' and configure the assembly plugin just so ;).
This is actually a little tricky to fix generically for maven as there's so many ways to create the jar; e.g. via any plugins like: jar, spring-boot, assembly, vertx, wildflyswarm etc. Plus the file name often includes the version inside as well; which would mean having to edit the Dockerfile once on
draft create
and then again for each time the version changes in thepom.xml
.I did wonder about trying to specify the
project.build.finalName
on the CLI in the mvn command but that doesn't seem to work, which is a shame.Replacing this:
with something like this seems to fix many use cases:
that certainly works for many spring boot apps that just make a single jar.
However the example project creates 2 jars which is gonna cause issues.
So I wonder if a better fix is to try keep the
Dockerfile
simple and try delegate more power to the pom.xml.We could use a
docker
maven profile which could add some custom configuration or steps to ensure that there will always be anapp.jar
created by copying/renaming the proper jar? Then theDockerfile
would work for all suitablepom.xml
files and never need changing - we'd then just need to tweakpom.xml
files to add the profile?Another option could be to add a maven plugin which is invoked after the packaging is created, to look at the pom and contents of
target
and make an educated guess if there is no explicit configuration in place - for which is the correct jar to use?e.g. something like switching this:
with
Then we can wrap up the logic to guess which jar should be used in a simple mvn plugin - which if well behaved pom.xml's do it already, there will be an
app.jar
so its a NOOP - otherwise the plugin can analyse the steps invoked so far to figure out the right jar to rename?Thoughts? The maven plugin seems the simplest and least likely to require any major changes to the
Dockerfile
or the end userspom.xml
- so maybe thats the best approach to start with? Then folks who know what they are doing and know a good canonical jar file can edit theDockerfile
to remove the plugin and use whatever name they choose?