Search code examples
javalinuxgradleredhatamazon-linux-2

How to set environment variables so they work in non-interactive bash shells?


I am running the amazonlinux:2 docker image directly from dockerhub and installing the corretto-17 JDK with the following command:

yum install -y git java-17-amazon-corretto-devel

Note: I am not using a custom Dockerfile, I do not control it and I can't change it.

When I then try and run my .gradlew task, it fails because there's no JAVA_HOME set. So I do that by:

echo "export JAVA_HOME='/usr/lib/jvm/java-17-amazon-corretto.x86_64'" >> /root/.bashrc

If I manually connect a terminal to to the container, the .bashrc works fine and gradlew will run.

But when I run commands from outside the container via something like:

docker exec kopibuild /bin/bash -c "cd the-project-code && ./gradlew build"

The .bashrc is not loaded so JAVA_HOME is not set and gradlew fails.

My workaround is to add the interactive flag -i to the bash command and then it all works, but there are warnings in the logs about "cannot set terminal process group (-1): Inappropriate ioctl for device".

docker exec kopibuild /bin/bash -c "cd the-project-code && BASH_ENV=/root/.bashrc ./gradlew build"

But it didn't seem to do anything.

What's the right way to set environment variables for Amazon Linux so they will exist in non-interactive shell invocations?


Solution

  • After digging around on the Googles - I believe there is no standard Linux way to set an environment variable for non-interactive shells.

    But there is a Docker way to answer the question. On the original docker create of the container from the amazonlinux:2 image, specify the environment variable via -e JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto.x86_64. This stores the environment variable in the docker metadata for the container and it will be available in all execution contexts, including non-interactive shells invoked directly via docker exec (without having to specify it explicitly for every exec command).

    As far as I know, this is the same as what the ENV command in a Dockerfile does.