user10690357
user10690357

Reputation:

How can I use bash-only syntax in CMD in a Dockerfile?

I am creating a Dockerfile which starts a Java application. This Java application is given a file path which contains the output of ls -l.

(Note that in my real Dockerfile I am not doing ls - l but rather complex commands. I altered that to ls - l to simplify the question.)

I tried the following:

FROM openjdk:8-jre

ARG JAR
COPY target/$JAR /app/app.jar

CMD java -jar /app/app.jar <( ls -l )

This bash <( ... ) construction should create a temporary file containing the output of ls -l.

When starting the Docker file, I get:

/bin/sh: 1: Syntax error: "(" unexpected

Now, sh does not support the <( ... ) construction, hence the error. How can I start the application safely via bash instead of sh? With safely I mean that the Java app still will receive all OS signals (SIGHUP, ...) and react appropriately.

Upvotes: 1

Views: 100

Answers (2)

David Maze
David Maze

Reputation: 158748

If you're doing complex things on startup it's often easier to write them into a script than try to build a very complicated command line. Once you're doing that, you can use the set of primitives that are available in the POSIX shell standard, even if they require multiple commands to do things that GNU bash could do inline.

For this I might write a script:

#!/bin/sh
ls -l >/ls-l.txt
exec java -jar /app/app.jar /ls-l.txt

and then copy it in as the default thing your image runs

FROM openjdk:8-jre
ARG JAR
COPY target/$JAR /app/app.jar
COPY launch-app.sh /usr/bin/app
# RUN chmod +x /usr/bin/app, if it's not already executable
CMD ["app"]

Upvotes: 1

Charles Duffy
Charles Duffy

Reputation: 295298

Replace your command with a JSON list, for which the first two elements are bash -c, and the last element is the shell command you actually want to run.

CMD ["bash", "-c", "exec java -jar /app/app.jar <( ls -l )"]

To generate such an array for a more complex command, you might consider using jq to ensure that syntax is correct, even for input with backslashes, newlines or quotes:

jq -cnRs '["bash", "-c", input]' <<'EOF'
# you can put other shell commands here if you need to
exec java -jar /app/app.jar <( ls -l )
EOF

exec ensures that the java instance replaces bash, and thus is sent signals directly.

Upvotes: 1

Related Questions