0

I'm trying to run a docker container that uses maven to deploy a java application Without using docker, the command that I use to deploy is "java -jar app-v0.1.jar"

Since the version of my application tends to change, (app-v0.1, v0.2 ...) what I usually do is running "java -jar *.jar" (There's always only 1 .jar file in the working folder). This works locally.

However, this seems to be unable to apply when building a Docker container. Here's my dockerfile


FROM openjdk:8

WORKDIR /app

COPY *.jar .

CMD ["java", "-jar", "*.jar"]

EXPOSE 8181


I can build the docker image from that Dockerfile. But when I try to run the container, I always get the Error: Unable to access jarfile *.jar.

I also tried:

COPY target/*.jar .

RUN file=`find . -name "*.jar" -exec basename {} \;`

CMD ["java", "-jar", "${file}"]

which returns Error: Unable to access jarfile ${file}

If I change the "*.jar" to a specific name, for example

CMD ["java", "-jar", "app-v0.1.jar"]

everything works normally. But clearly I don't want to change my Dockerfile every time there's a code update in my app.

Is there a way in which I can put variables in the Dockerfile, something like "

CMD ["java", "-jar", "${filename}.jar"] "?

(If this helps: I'm using Jenkins pipeline to automate the docker building process)

Hien Le
  • 301
  • 3
  • 14
  • You problem seem a duplicate of the following question: https://stackoverflow.com/questions/40873165/use-docker-run-command-to-pass-arguments-to-cmd-in-dockerfile – Arkadi May 23 '19 at 05:48
  • Normally maven builds your application in "target". So "COPY target/*.jar ." fixed your copy issue. Now you can go back to also run "*.jar" and it will work. – Mihai May 23 '19 at 05:51
  • @Mihai I actually wanted to simplify my question so I just wrote down "COPY **.jar" I do in fact do "COPY target/*.jar" in my dockerfile. – Hien Le May 23 '19 at 06:15
  • @Arkadi Thanks. I did read your mentioned question before posting this, but couldn't solve my problem. Maybe I did something wrong when following the approved answer. – Hien Le May 23 '19 at 06:17

2 Answers2

1

I recommend to use a multi-stage build.

Your Dockerfile should be:

FROM maven:3.6.0-jdk-8 as build

ARG BUILD_PROFILE=prod

WORKDIR /apps

COPY . .
RUN mvn --activate-profiles ${BUILD_PROFILE} clean install

FROM openjdk:8-jre
COPY --from=build /apps/target/*.jar ./
COPY startup.sh ./

RUN chmod +x ./*.sh
ENTRYPOINT ["/startup.sh"]

And startup.sh:

#!/usr/bin/env bash
java -Dspring.profiles.active=${RUN_PROFILE} -jar /app*.jar

This way you also build your application when you do a docker build.

NOTE you can also use the command in startup.sh as your entrypoint but I find it cleaner this way.

Mihai
  • 9,526
  • 2
  • 18
  • 40
0

Solution 1:

Use ARG, see this:

FROM openjdk:8

ARG filename
ENV jarname=${filename}

WORKDIR /app

COPY *.jar .

CMD java -jar ${jarname}

EXPOSE 8181

The use docker build --build-arg filename=a.jar xxx

Solution 2:

Use ENV, see this:

FROM openjdk:8

ENV jarname=""

WORKDIR /app

COPY *.jar .

CMD java -jar ${jarname}

EXPOSE 8181

Pass env to when container run docker run -e jarname=a.jar xxx

Solution 3:

Make * work in shell:

FROM openjdk:8

WORKDIR /app

COPY *.jar .

CMD java -jar *.jar

EXPOSE 8181
atline
  • 28,355
  • 16
  • 77
  • 113
  • Thanks. Solution 3 works for me. The other 2 don't. But what's the difference when using square brackets in the CMD stage? – Hien Le May 23 '19 at 06:27
  • Yes, you are correct. I forget only the shell can get the env variable... Update 1&2. – atline May 23 '19 at 06:34
  • And if use `[]`, this means it will not use shell. So `*` cannot work. Have a look for this: http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/, also this: https://docs.docker.com/engine/reference/builder/#cmd – atline May 23 '19 at 06:35