Subtle Difference in Dockerfile and Dockercompose – Variables in Entrypoints

TLDR: Variables in Entrypoints should be escaped. This can be done by using a second $.

Background

While setting up a Spark Thrift Server i encountered a – in retrospective – obvious oversight. I would always get the following Error, which in itself is just a side effect of how i had a little upsy daisy configuration in my dockercompose file.

org.apache.spark.SparkException: Invalid Spark URL: spark://CoarseGrainedScheduler@:33981

The goal of my project was to setup up a Spark Cluster using docker compose including the Thrift Server. Lets dive into this little example.

Things did work initially

In my Dockerfile I had following entrypoint:

ENTRYPOINT "/bin/bash", "-c", "DRIVER_HOST=$(hostname -i | tr ' ' '\n' | head -n 1) && echo $DRIVER_HOST && ./sbin/start-thriftserver.sh --conf spark.driver.host=$DRIVER_HOST --conf spark.driver.bindAddress=$DRIVER_HOST"

This would make the THrift Server running on its own container. The enviroment variables are set to be able to communicate with the master node.

Somehow things did not work anymore

Now the almost exact configuration copied into my dockercompose, with just a change of directive, somehow made the Thrift Server throw the above mentioned error.

entrypoint: ["/bin/bash", "-c", "DRIVER_HOST=$(hostname -i | tr ' ' '\n' | head -n 1) && echo $DRIVER_HOST && ./sbin/start-thriftserver.sh --conf spark.driver.host=$DRIVER_HOST --conf spark.driver.bindAddress=$DRIVER_HOST"]

Some resources point out system related problems (stackoverflow). However, as we already figured out, it only occurs, when i use the command in the entrypoint of the dockercompose but not when its in the Dockerfile. The entrypoint of the dockercompose should also just replace the Dockerfile and everything should work out perfectly as expected.

WARN[0000] The “DRIVER_HOST” variable is not set. Defaulting to a blank string.

I call myself guilty of overlooking warning messages. What are they for anyway right? Well in this case, this message, after running docker compose up, reported exactly why my compose configuration failed. However, I was not able to understand the impact of its message until I came to the solution. Mind you, even chatgpt gave me an all ok and translated the entrypoint command from the Dockerfile just like above for the dockercompose.

Debugging my problem finally revealed, that somehow the code in the Dockerfile would echo a DRIVER_HOST, while the code in dockercompose did not! This caused the above mentioned error.

Resolution

But why is that so?

The reason is that when parsing the Docker Compose file, it replaces variables with environment variables specified in the .env file or in the environment where Docker Compose is run. However, in this case, it unintentionally replaced a variable before the script was executed. This caused an issue because we needed to generate the DRIVER_HOST variable within the script itself at runtime.

To prevent this premature substitution, we escaped the DRIVER_HOST variable by using $$DRIVER_HOST in the entrypoint. This way, the variable is preserved as is during the Docker Compose parsing phase and is correctly set during the execution of the script inside the container (see stackoverflow).

Leave a Comment

Your email address will not be published. Required fields are marked *

hungsblog | Nguyen Hung Manh | Dresden
Scroll to Top