Search code examples
dockerdockerfile

Dynamically set JAVA_HOME and import certs into cacerts passing JAVA_HOME as path


I want to dynamically set JAVA_HOME and import self-signed certs into cacerts by passing JAVA_HOME as path. Below is my docker file. I got below error

keytool error: java.io.FileNotFoundException: /jre/lib/security/cacerts (No such file or directory).

Please help me. Also I don't want use any entrypoint here.

RUN export JAVA_HOME="$(dirname $(dirname $(readlink -f $(which javac))))" && \
    echo $JAVA_HOME

RUN keytool -import -file /home/vmdso/self-inter.cer -alias hellointer -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -noprompt 

When I run docker build. I see JAVA_HOME is displaying properly

Step 11/21 : RUN export JAVA_HOME="$(dirname $(dirname $(readlink -f $(which javac))))" &&     echo $JAVA_HOME
 ---> Running in 66e19192a500
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.272.b10-1.amzn2.0.1.x86_64

Solution

  • Each RUN statement runs in it's own context, so variables exported in one RUN statement is not accessible in the next. Consider the following example

    From ubuntu:latest
    
    RUN export JAVA_HOME="MYJAVAHOME" && \
        echo "JAVA_HOME_1 $JAVA_HOME"
    
    RUN echo "JAVA_HOME_2 $JAVA_HOME"
    

    Building this using docker build . yields

    Sending build context to Docker daemon  2.048kB
    Step 1/3 : From ubuntu:latest
     ---> 1d622ef86b13
    Step 2/3 : RUN export JAVA_HOME="MYJAVAHOME" &&     echo "JAVA_HOME_1 $JAVA_HOME"
     ---> Running in 3cc553c514ba
    JAVA_HOME_1 MYJAVAHOME
    Removing intermediate container 3cc553c514ba
     ---> f736163d33fb
    Step 3/3 : RUN echo "JAVA_HOME_2 $JAVA_HOME"
     ---> Running in 5c4b550cd96c
    JAVA_HOME_2
    Removing intermediate container 5c4b550cd96c
     ---> fe57a6e916ae
    Successfully built fe57a6e916ae
    

    AS you can see, JAVA_HOME can be echoed in the first RUN statement, but not in the second. This is because JAVA_HOME is set in the context of the first RUN statement.

    To achieve what you want you would need to also do your import in the same RUN statement:

    RUN export JAVA_HOME="$(dirname $(dirname $(readlink -f $(which javac))))" && \
        keytool -import -file /home/vmdso/self-inter.cer -alias hellointer -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -noprompt
    

    On the other hand, do you really have a need to figure out JAVA_HOME dynamically?, Normally you would use a base image where Java is installed already or you have installed in your Dockerfile. In both cases the location should be known beforehand and thus you can use ENV instead (which would also set JAVA_HOME in the final image):

    ENV JAVA_HOME "/opt/bin/java"
    
    RUN keytool -import -file /home/vmdso/self-inter.cer -alias hellointer -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -noprompt