Search code examples
rdockerjenkinsrjava

Docker, Jenkins, and rJava


Part of a Jenkins job I'm running entails installing rJava; the Jenkins job is running on a docker image over which I have control, but still I can't seem to get rJava to install.

Looking around a bit, it seems like being sure to run R CMD javareconf is pretty key in all this, and indeed I added && R CMD javareconf as the last command in my Dockerfile. Compilation of the Docker image contains:

Java interpreter : /docker-java-home/jre/bin/java
Java version     : 1.8.0_171
Java home path   : /docker-java-home
Java compiler    : /docker-java-home/bin/javac
Java headers gen.: /docker-java-home/bin/javah
Java archive tool: /docker-java-home/bin/jar

trying to compile and link a JNI program 
detected JNI cpp flags    : -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
detected JNI linker flags : -L$(JAVA_HOME)/jre/lib/amd64/server -ljvm
gcc -std=gnu99 -I/usr/share/R/include -DNDEBUG -I/docker-java-home/include -I/docker-java-home/include/linux     -fpic  -g -O2 -fdebug-prefix-map=/build/r-base-3.3.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c conftest.c -o conftest.o
gcc -std=gnu99 -shared -L/usr/lib/R/lib -Wl,-z,relro -o conftest.so conftest.o -L/docker-java-home/jre/lib/amd64/server -ljvm -L/usr/lib/R/lib -lR


JAVA_HOME        : /docker-java-home
Java library path: $(JAVA_HOME)/jre/lib/amd64/server
JNI cpp flags    : -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
JNI linker flags : -L$(JAVA_HOME)/jre/lib/amd64/server -ljvm
Updating Java configuration in /usr/lib/R
Done.

Now, when I enter the Docker instance (docker exec -it jenkins_img bash), I can in fact manually install rJava: install.packages('rJava') works as expected; importantly, this is part of the output there:

checking Java support in R... present:
interpreter : '/docker-java-home/jre/bin/java'
archiver    : '/docker-java-home/bin/jar'
compiler    : '/docker-java-home/bin/javac'
header prep.: '/docker-java-home/bin/javah'
cpp flags   : '-I/docker-java-home/include -I/docker-java-home/include/linux'
java libs   : '-L/docker-java-home/jre/lib/amd64/server -ljvm'

However, when I run the script that's part of my Jenkins job, the corresponding output becomes:

checking Java support in R... present:
interpreter : '/usr/lib/jvm/default-java/jre/bin/java'
archiver    : '/usr/lib/jvm/default-java/bin/jar'
compiler    : '/usr/lib/jvm/default-java/bin/javac'
header prep.: '/usr/lib/jvm/default-java/bin/javah'
cpp flags   : '-I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux'
java libs   : '-L/usr/lib/jvm/default-java/jre/lib/amd64/server -ljvm'
checking whether Java run-time works... ./configure: line 3747: /usr/lib/jvm/default-java/jre/bin/java: No such file or directory
no
configure: error: Java interpreter '/usr/lib/jvm/default-java/jre/bin/java' does not work

So, it seems whichever process is running when I docker exec to bash has a different JAVA_HOME than the process which is running under my Jenkins job. To that end, I added the following directly before the line installing rJava in my script (as suggested):

export JAVA_HOME=/docker-java-home/
export PATH=$PATH:$JAVA_HOME/bin
Rscript -e 'install.packages("rJava")'

However, this fails with the same output. I have also checked that the R process running install.packages has the same JAVA_HOME by cating Sys.getenv('JAVA_HOME') and confirming that it's /docker-java-home/.

The Jenkins script doesn't have root access so I can't run R CMD javareconf there.

How can I get install.packages('rJava') to use the right JAVA_HOME?


Solution

  • FWIW, these days I use some variation of the following in Docker images to get rJava to build correctly:

    # rJava
    RUN apt-get update && apt-get install -y libudunits2-dev gnupg2 software-properties-common
    RUN echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" \
          | tee /etc/apt/sources.list.d/webupd8team-java.list \
        &&  echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" \
          | tee -a /etc/apt/sources.list.d/webupd8team-java.list \
        && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EEA14886 \
        && echo "oracle-java8-installer shared/accepted-oracle-license-v1-1 select true" \
            | /usr/bin/debconf-set-selections \
        && apt-get update \
        && apt-get install -y oracle-java8-installer \
        && update-alternatives --display java \
        && rm -rf /var/lib/apt/lists/* \
        && apt-get clean \
        && R CMD javareconf
    

    This was not particularly my own work, I basically took it from @daroczig:

    https://github.com/rocker-org/rocker/issues/109

    https://hub.docker.com/r/cardcorp/r-java/dockerfile/