Search code examples
javadockerdockerfilecoredumpadoptopenjdk

How to add AdoptOpenJDK to Docker image?


I've created a generic docker building file which includes utilities such as kubectl and Helm, but now I want to add adoptopenjdk to the image along with Maven, but when I test it Java crashes with a core dump.

Here is the Dockerfile:

# docker-build-test-image

FROM    docker:stable-git

ENV     KUBERNETES_VERSION 1.11.10
ENV     HELM_VERSION 2.14.0
ENV     JDK_FILE=OpenJDK11U-jdk_x64_linux_hotspot_11.0.4_11.tar.gz
ENV     JDK_DIR=/opt/jdk-11.0.4+11
ENV     LANG=C.UTF-8
ENV     MAVEN_FILE apache-maven-3.3.9-bin.tar.gz

RUN     apk update && \
        apk add --no-cache curl && \
        apk add --no-cache bash && \
        apk add --no-cache jq && \
        apk add --no-cache gettext && \
        apk add --no-cache wget

RUN     apk add -U openssl curl tar gzip bash ca-certificates git && \
        curl -L -o /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \
        curl -L -O https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.28-r0/glibc-2.28-r0.apk && \
        apk add glibc-2.28-r0.apk && \
        rm glibc-2.28-r0.apk

RUN     curl "https://kubernetes-helm.storage.googleapis.com/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | tar zx && \
        mv linux-amd64/helm /usr/bin/ && \
        mv linux-amd64/tiller /usr/bin/ && \
        helm version --client && \
        tiller -version

RUN     curl -L -o /usr/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl" && \
        chmod +x /usr/bin/kubectl && \
        kubectl version --client

# https://github.com/frol/docker-alpine-glibc/blob/master/Dockerfile
# Here we install GNU libc (aka glibc) and set C.UTF-8 locale as default.

RUN ALPINE_GLIBC_BASE_URL="https://github.com/sgerrand/alpine-pkg-glibc/releases/download" && \
    ALPINE_GLIBC_PACKAGE_VERSION="2.28-r0" && \
    ALPINE_GLIBC_BASE_PACKAGE_FILENAME="glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    ALPINE_GLIBC_BIN_PACKAGE_FILENAME="glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    ALPINE_GLIBC_I18N_PACKAGE_FILENAME="glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    apk add --no-cache --virtual=.build-dependencies wget ca-certificates && \
    echo \
        "-----BEGIN PUBLIC KEY-----\
        MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApZ2u1KJKUu/fW4A25y9m\
        y70AGEa/J3Wi5ibNVGNn1gT1r0VfgeWd0pUybS4UmcHdiNzxJPgoWQhV2SSW1JYu\
        tOqKZF5QSN6X937PTUpNBjUvLtTQ1ve1fp39uf/lEXPpFpOPL88LKnDBgbh7wkCp\
        m2KzLVGChf83MS0ShL6G9EQIAUxLm99VpgRjwqTQ/KfzGtpke1wqws4au0Ab4qPY\
        KXvMLSPLUp7cfulWvhmZSegr5AdhNw5KNizPqCJT8ZrGvgHypXyiFvvAH5YRtSsc\
        Zvo9GI2e2MaZyo9/lvb+LbLEJZKEQckqRj4P26gmASrZEPStwc+yqy1ShHLA0j6m\
        1QIDAQAB\
        -----END PUBLIC KEY-----" | sed 's/   */\n/g' > "/etc/apk/keys/sgerrand.rsa.pub" && \
    wget \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
    apk add --no-cache \
        "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
    \
    rm "/etc/apk/keys/sgerrand.rsa.pub" && \
    /usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 "$LANG" || true && \
    echo "export LANG=$LANG" > /etc/profile.d/locale.sh && \
    \
    apk del glibc-i18n && \
    \
    rm "/root/.wget-hsts" && \
    apk del .build-dependencies && \
    rm \
        "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME"

WORKDIR /tmp
RUN     chmod 755 /opt
COPY    $JDK_FILE /tmp/
RUN     tar -zvxf /tmp/$JDK_FILE -C /opt/ \
        && rm /tmp/$JDK_FILE
ENV     JAVA_HOME $JDK_DIR
ENV     PATH "$PATH:$JDK_DIR/bin"

RUN     wget --no-cookies --no-check-certificate "https://archive.apache.org/dist/maven/maven-3/3.3.9/binaries/$MAVEN_FILE"
RUN     pwd
RUN     ls -ltr
RUN     tar -zvxf $MAVEN_FILE  -C /opt/
RUN     rm $MAVEN_FILE
ENV     PATH "$PATH:/opt/apache-maven-3.3.9/bin"

COPY    ./settings.xml /root/.m2/

The JDK_FILE "OpenJDK11U-jdk_x64_linux_hotspot_11.0.4_11.tar.gz" was downloaded directly from https://adoptopenjdk.net/releases.html?variant=openjdk11&jvmVariant=hotspot.

A really simple Java test file:

class HelloWorld 
{ 
    public static void main(String args[]) 
    { 
        System.out.println("Hello, World"); 
    } 
}

And I'm building it via GitLab pipeline:

image: ${BUILD_URL}/tools/build/docker-build-test-image/add-jdk:20191129.33

stages:
  - build

build:
  stage: build
  script:
    - java -version
    - javac HelloWorld.java
    - java HelloWorld

And here is the output:

$ java -version
openjdk version "11.0.4" 2019-07-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.4+11)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.4+11, mixed mode)
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  [thread 20 also had an error]SIGSEGV
 (0xb) at pc=0x00007f0c0251bba1, pid=18, tid=28
#
# JRE version: OpenJDK Runtime Environment (11.0.4+11) (build 11.0.4+11)
# Java VM: OpenJDK 64-Bit Server VM (11.0.4+11, mixed mode, tiered, compressed oops, serial gc, linux-amd64)
# Problematic frame:
# C  [libc.so.6+0x117ba1]
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e %P %I %h" (or dumping to /builds/d4e/playground/revills/java_test/core.18)
#
# An error report file with more information is saved as:
# /builds/d4e/playground/revills/java_test/hs_err_pid18.log
[thread 19 also had an error]
#
# If you would like to submit a bug report, please visit:
#   https://github.com/AdoptOpenJDK/openjdk-build/issues
#
/bin/bash: line 111:    18 Aborted                 (core dumped) java -version

Could you please let me know what I have done wrong?

Cheers, Steve


Solution

  • If you build on basic alpine, you can add in the open-jdk and maven. It might look something like this:

    from alpine:3.10
    
    run apk --no-cache add openjdk11 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community
    run apk add bash vim curl wget jq docker git tar unzip bash-completion ca-certificates
    run cd /opt && curl -sSl http://mirror.vorboss.net/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz | tar -xz
    
    env PATH "$PATH:/opt/apache-maven-3.6.3/bin"
    entrypoint ["/bin/bash"]
    

    This will set up an alpine image with java 11 and the latest maven (as of writing). Typically we'd do this with a single run command to minimise the number of layers in our image, but I'll leave that optimisation to your imagination.

    I've added a line showing how and where to install other tools, like Docker, bash, vim, curl, etc. Some of these are used installing maven (tar unzip), and some are just for decoration. You only really need curl, tar, and unzip, to answer this question, but as you're building a devbox I thought I'd add some more for demonstration.

    When you are deciding which base image to use for a project like this, it's often best to start with the base OS, like apline:3, rather than some random image that happens to have one thing you need installed in it (git in your example). Treat it like OO -- you are inheriting the git image, so you're also a git image. In your case, you're not really a git image, you're a swiss-army knife and you've no idea what the underlying os really is with another choice (and if you use :latest as the tag you've no idea what it will become in the future).