0

I am trying to parameterize the final jar file name in docker build. I need docker-maven-plugin to take jar file name passed via command line parameter. Maven build is not throwing any error while building image.

If I hard-code the jar file name in dockerfile, it is working fine.

Maven command to docker build:

mvn -X -s settings.xml docker:build -DJAR_FILE_NAME=${filename}

My docker file:

RUN curl -kfsSL https://example.com/UnlimitedJCEPolicyJDK8/US_export_policy.jar > US_export_policy.jar \
&& curl -kfsSL https://example.com//UnlimitedJCEPolicyJDK8/local_policy.jar > local_policy.jar \
    && mv local_policy.jar ${JAVA_HOME}/jre/lib/security \
    && mv US_export_policy.jar ${JAVA_HOME}/jre/lib/security \
    && rm -rf US_export_policy.jar local_policy.jar 

ENV JAVA_KEYSTORE ${JAVA_HOME}/jre/lib/security/cacerts
RUN curl -kfsSL https://example.com/mycert.cer > mycert.cer \
    && ${JAVA_HOME}/bin/keytool -v -importcert -file mycert.cer -keystore ${JAVA_KEYSTORE} -storepass dummy -alias dummy -noprompt \
    && rm mycert.cer

VOLUME /tmp
#ADD myservice-2.0.2-SNAPSHOT.jar app.jar   <-hard-coded name works fine

RUN echo "final jar file name"
RUN echo ${JAR_FILE_NAME}

ADD ${JAR_FILE_NAME} app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

My POM.xml

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.4.0</version>
    <configuration>
        <imageName>${docker.image.prefix}/myservice</imageName>
        <dockerDirectory>src/main/docker</dockerDirectory>
        <resources>
            <resource>
                <targetPath>${docker.resource.targetPath}</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
    </configuration>
</plugin>

Output from docker build process:

Step 6 : VOLUME /tmp
 ---> Using cache
 ---> xxxxxxxxx
Step 7 : RUN /bin/bash -c echo JAR_FILE_NAME1 in docker :$JAR_FILE_NAME
 ---> Using cache
 ---> xxxxxxxxx
Step 8 : RUN /bin/bash -c echo JAR_FILE_NAME2 in docker :${JAR_FILE_NAME}
 ---> Using cache
 ---> xxxxxxxxx
Step 9 : RUN echo $JAR_FILE_NAME
 ---> Using cache
 ---> xxxxxxxxx
Step 10 : RUN echo "final jar file name"
 ---> Using cache
 ---> xxxxxxxxx
Step 11 : RUN echo ${JAR_FILE_NAME}
 ---> Using cache
 ---> xxxxxxxxx
Step 12 : ADD ${JAR_FILE_NAME} app.jar
 ---> Using cache
 ---> xxxxxxxxx
Step 13 : RUN bash -c 'touch /app.jar'
 ---> Using cache
 ---> xxxxxxxxx
Step 14 : ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar /app.jar
 ---> Using cache
 ---> xxxxxxxxx
Successfully built xxxxxxxxx
[INFO] Built xxx/myservice

Output while pulling image:

I0603 13:48:32.849159 23106 exec.cpp:132] Version: 0.23.0
I0603 13:48:32.857393 23114 exec.cpp:206] Executor registered on slave 20170523-104056-1453378314-5050-11670-S48
Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.
Error: Invalid or corrupt jarfile /app.jar
bkrish
  • 627
  • 1
  • 11
  • 23

3 Answers3

1

Why don't you use a regular docker build command instead of going through maven? You can use a maven base image, something like maven:onbuild even. An example here may help.

Anoop
  • 1,406
  • 2
  • 13
  • 20
  • I have a whole bunch of Maven and Quality gates stuff running in Jenkins CI server. Also the base image is a "custom" image that should be used. So cannot move out of maven for now! :( – bkrish Jun 05 '17 at 16:22
0

I parameterized the output jar to be used in docker image in this way.

  1. In Dockerfile, used a concrete name without any version. Removed ${JAR_FILE_NAME}, dynamic parameters from Dockerfile.

ADD myservice.jar app.jar

  1. In POM.xml, I made maven to output artifact without version in the jar file name, by adding below element right under tag.

<finalName>${project.artifactId}</finalName>

So, no manual update needed for Dockerfile. Forgetting to update Dockerfile and then build getting failed was really disturbing. I let Maven to manage versions and those versions are used as finite image tags, and thus "reproducible builds" work for me.

bkrish
  • 627
  • 1
  • 11
  • 23
0

I had the same kind of problem: I dont't want to hard-code the project version in my Dockerfile.

I first though about removing the version in the jar's file name (this can be achieved using your build tool, I personnaly use gradle). Yet I was quite unhappy with it since I consider having the version in jar's name is a good practice (there is an interstning discustion about this in this question for instance).

So I came up with this solution: copy/add the jar using a wildcard:

FROM eclipse-temurin:17-jre-alpine
WORKDIR /app/
COPY ./path/to/my/jar/*.jar /app/my-app.jar
ENTRYPOINT ["java", "-jar",  "/app/my-app.jar"]

Here I managed to make my build tool produce the jar I want alone in its folder. The point is to have a way to use a wildcard to get this single jar without ambiguity.