belgoros
belgoros

Reputation: 3908

Dockerfile with parametrization: fails with XXX

I have the following Dockerfile in a simple Spring Boot app:

FROM maven:3.6-jdk-8-alpine as build

WORKDIR /app

COPY ./pom.xml ./pom.xml

RUN mvn dependency:go-offline -B

# copy your other files
COPY ./src ./src

# build for release
RUN mvn package -DskipTests

FROM openjdk:8-jre-alpine
ARG artifactid
ARG version
ENV artifact ${artifactid}-${version}.jar
WORKDIR /app

COPY --from=build /app/target/${artifact} /app

EXPOSE 8080

ENTRYPOINT ["sh", "-c"]

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

When I build it with the required arguments:

docker build --build-arg artifactid=spring-demo --build-arg version=0.0.1 -t spring-demo .

it builds with no errors.

When I try to run the image with:

docker container run -it spring-demo

it fails with the following error:

Usage: java [-options] class [args...]
           (to execute a class)
   or  java [-options] -jar jarfile [args...]
           (to execute a jar file)
where options include:
    -d32      use a 32-bit data model if available
    -d64      use a 64-bit data model if available
    -server   to select the "server" VM
                  The default VM is server,
                  because you are running on a server-class machine.


    -cp <class search path of directories and zip/jar files>
    -classpath <class search path of directories and zip/jar files>
                  A : separated list of directories, JAR archives,
                  and ZIP archives to search for class files.
    -D<name>=<value>
                  set a system property
    -verbose:[class|gc|jni]
                  enable verbose output
    -version      print product version and exit
    -version:<value>
                  Warning: this feature is deprecated and will be removed
                  in a future release.
                  require the specified version to run
    -showversion  print product version and continue
    -jre-restrict-search | -no-jre-restrict-search
                  Warning: this feature is deprecated and will be removed
                  in a future release.
                  include/exclude user private JREs in the version search
    -? -help      print this help message
    -X            print help on non-standard options
    -ea[:<packagename>...|:<classname>]
    -enableassertions[:<packagename>...|:<classname>]
                  enable assertions with specified granularity
    -da[:<packagename>...|:<classname>]
    -disableassertions[:<packagename>...|:<classname>]
                  disable assertions with specified granularity
    -esa | -enablesystemassertions
                  enable system assertions
    -dsa | -disablesystemassertions
                  disable system assertions
    -agentlib:<libname>[=<options>]
                  load native agent library <libname>, e.g. -agentlib:hprof
                  see also, -agentlib:jdwp=help and -agentlib:hprof=help
    -agentpath:<pathname>[=<options>]
                  load native agent library by full pathname
    -javaagent:<jarpath>[=<options>]
                  load Java programming language agent, see java.lang.instrument
    -splash:<imagepath>
                  show splash screen with specified image
See http://www.oracle.com/technetwork/java/javase/documentation/index.html for more details.

What's wrong with the above settings, please? The app example code can be found here.

Upvotes: 0

Views: 607

Answers (3)

David Maze
David Maze

Reputation: 158647

You should delete that ENTRYPOINT line and use the shell form of CMD.

# No ENTRYPOINT
CMD java -jar ${artifact}

The Dockerfile ENTRYPOINT and CMD lines get combined into a single command line. In your Dockerfile, that gets interpreted as

sh -c java '-jar ${artifact}'

But the sh -c option only actually takes the next single word and interprets it as the command to run; so that really gets processed as

sh -c 'java' # '-jar ${artifact}'

ignoring the -jar option.

There are two ways to "spell" CMD (and ENTRYPOINT and RUN). As you've done it with JSON arrays, you specify exactly the "words" that go into the command line, so for example, -jar ${artifact} would be passed as a single argument including the embedded space. If you just pass a command line, Docker will insert a sh -c wrapper for you, and the shell will handle word parsing and variable interpolation. You shouldn't ever need to manually include sh -c in a Dockerfile.

Upvotes: 2

Peaceful James
Peaceful James

Reputation: 2235

ENV variables are only available during the build. To get env variables into the container at runtime, you have to use --env or -e or --env-file. It is best to use --env-file.

See this for same problem answered already: How do I pass environment variables to Docker containers? Also look at this: Use environment variables in CMD

Here is one possible solution:

  1. Keep your CMD instruction as this:
CMD ["java","-jar ${artifact}"]
  1. Use this docker run command:
docker container run -it -e artifact=spring-demo-0.0.1.jar spring-demo

Upvotes: 0

CLNRMN
CLNRMN

Reputation: 1457

It looks to me that you have an error with the sh -c. The arguments are not read correctly. You could check that if you do a docker inspect on the exited container. In the output search for the "CMD".

ENTRYPOINT ["sh", "-c"]

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

If you would like to run it with sh -c, you have to quote the arguments as one like:

CMD ["java -jar ${artifact}"]

Can you give it a try?

Upvotes: 1

Related Questions