Keith
Keith

Reputation: 4204

How can I update a variable in my dockerfile based on the value of another variable?

I need to update my JAVA_ARGS variable before I send it to to the java -server command.

When a user calls ./script/server -d, I want to append debug arguments. Here's the related part of my ./script/server:

for i in "$@"
do
case $i in
    -d|--debug)
    DEBUG_ARGS="--build-arg DEBUG_MODE=true"
    shift
    ;;
    -h|--help)
    display_usage
    exit
    ;;
    *)
    echo "Unknown option"
    exit 1
    ;;
esac
done

docker-compose build ${DEBUG_ARGS} app
docker-compose up

Here is a snippet from my docker-compose.yml

services:
  app:
    environment:
      ...
      JAVA_ARGS: -Xms2048m -Xmx3072m
      JAVA_ARGS_DEBUG: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5080

This seems to work, and I think my dockerfile is correctly detecting the DEBUG_MODE=true variable. Here's my dockerfile: (some things removed)

FROM openjdk:8-alpine

ARG DEBUG_MODE=false
ENV DEBUG_MODE ${DEBUG_MODE}

ARG JAVA_ARGS=
ENV JAVA_ARGS ${JAVA_ARGS}    

RUN if [ $DEBUG_MODE == "true" ]; \
        then echo "Debug mode on."; JAVA_ARGS=$JAVA_ARGS $JAVA_ARGS_DEBUG; \
        else echo "Debug mode off."; \
    fi;

RUN echo "Echoing JAVA_ARGS: "; \
    echo "${JAVA_ARGS}";

ENTRYPOINT ["/docker-entrypoint.sh"]
CMD java -server ${JAVA_ARGS} -jar /app/app.jar

I correctly see Debug mode on. output to the console.

But then echo "${JAVA_ARGS}"; is blank. And, indeed, when it gets to the last line, the args are not passed to the java command, and debugging is not enabled.

My bash is pretty shaky, do you know why I'm not able to update and use that var in the final command?

Upvotes: 0

Views: 297

Answers (1)

David Maze
David Maze

Reputation: 159352

You should make these options configurable at run time, and not try to "bake in" settings into the Docker image. (If the image has a 3 GB heap size hard-coded, can I run it on a system with only 1 GB of RAM? Or 64 GB?)

Your Dockerfile hints at an ENTRYPOINT script and that's a good place to put settings like this. We might trim the Dockerfile down to:

FROM openjdk:8-alpine
WORKDIR /app
COPY app.jar docker-entrypoint.sh ./
ENTRYPOINT "/app/docker-entrypoint.sh"
CMD ["java", "-jar", "app.jar"]

Then the entrypoint script can make decisions, based on command-line options or environment variables:

#!/bin/sh
if [ -n "$JAVA_OPTS" ]; then
  JAVA_OPTS="-Xms2048m -Xmx3072m"
fi
if [ -n "$DEBUG_MODE" ]; then
  JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5080"
fi
export JAVA_OPTS
exec "$@"

And then run it:

docker run --rm -p127.0.0.1:5080:5080 -e DEBUG_MODE=yes myimage

You'd run the same image "for debugging" or "for real"; you don't need to recompile it or make docker build time decisions about how to set variables.

Upvotes: 1

Related Questions