Small Alpine Linux containers with Java

Update

2019.10.21

The original post was about Java 13. Oracle is changing JDK versions quite frequently. The newest version of JDK is 14:

https://download.java.net/java/early_access/alpine/15/binaries/openjdk-14-ea+15_linux-x64-musl_bin.tar.gz

Intro

Quite often I hear a complaint from developers that Java containers are too big and how much smaller this would be with Go or other languages. With this new project called Portola it is possible to make very small (~40MB) containers running Java applications. Alpine Linux became the de facto standard for small containers but until now it was a rather complex process to create a Java environment using it. This is not anymore the case. Let’s see how we can leverage Project Portola to create these small containers.

Creating Containers

First, we just create a container that has a new small size JDK.

FROM alpine:latest as build

ADD https://download.java.net/java/early_access/alpine/15/binaries/openjdk-14-ea+15_linux-x64-musl_bin.tar.gz /opt/jdk/
RUN tar -xzvf /opt/jdk/openjdk-14-ea+15_linux-x64-musl_bin.tar.gz -C /opt/jdk/

RUN ["/opt/jdk/jdk-14/bin/jlink", "--compress=2", \      "--module-path", "/opt/jdk/jdk-14/jmods/", \      "--add-modules", "java.base", \      "--output", "/jlinked"]

FROM alpine:latest
COPY --from=build /jlinked /opt/jdk/
CMD ["/opt/jdk/bin/java", "--version"]

Enter fullscreen mode Exit fullscreen mode

The rest of the article is not concerned with JDK version. Output from docker build might reflect earlier version.

We can start to build the container:

[v@alpine-java jdk14_v]$ sudo docker build .
Sending build context to Docker daemon   2.56kB
Step 1/8 : FROM alpine:latest as build
latest: Pulling from library/alpine
bdf0201b3a05: Pull complete Digest: sha256:28ef97b8686a0b5399129e9b763d5b7e5ff03576aa5580d6f4182a49c5fe1913
Status: Downloaded newer image for alpine:latest
 ---> cdf98d1859c1
Step 2/8 : ADD https://download.java.net/java/early_access/alpine/16/binaries/openjdk-13-ea+16_linux-x64-musl_bin.tar.gz /opt/jdk/
Downloading [==================================================>]  195.2MB/195.2MB
 ---> Using cache
 ---> b1a444e9dde9
Step 3/7 : RUN tar -xzvf /opt/jdk/openjdk-13-ea+16_linux-x64-musl_bin.tar.gz -C /opt/jdk/
 ---> Using cache
 ---> ce2721c75ea0
Step 4/7 : RUN ["/opt/jdk/jdk-13/bin/jlink", "--compress=2",      "--module-path", "/opt/jdk/jdk-13/jmods/",      "--add-modules", "java.base",      "--output", "/jlinked"]
 ---> Using cache
 ---> d7b2793ed509
Step 5/7 : FROM alpine:latest
 ---> cdf98d1859c1
Step 6/7 : COPY --from=build /jlinked /opt/jdk/
 ---> Using cache
 ---> 993fb106f2c2
Step 7/7 : CMD ["/opt/jdk/bin/java", "--version"] - to check JDK version
 ---> Running in 8e1658f5f84d
Removing intermediate container 8e1658f5f84d
 ---> 350dd3a72a7d
Successfully built 350dd3a72a7d

Enter fullscreen mode Exit fullscreen mode

Even though the JDK image is 195MB the build is only 41MB. We can tag the image.

[v@alpine-java jdk13_v]$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              350dd3a72a7d        21 seconds ago      41.7MB
<none>              <none>              d7b2793ed509        25 minutes ago      565MB
alpine              latest              cdf98d1859c1        2 weeks ago         5.53MB
[v@alpine-java jdk13_v]$ sudo docker tag 350dd3a72a7d jdk-13-musl/jdk-version:v1
[v@alpine-java jdk13_v]$ sudo docker images
REPOSITORY                TAG                 IMAGE ID            CREATED              SIZE
jdk-13-musl/jdk-version   v1                  350dd3a72a7d        About a minute ago   41.7MB
<none>                    <none>              d7b2793ed509        27 minutes ago       565MB
alpine                    latest              cdf98d1859c1        2 weeks ago          5.53MB

Enter fullscreen mode Exit fullscreen mode

Running the container:

[v@alpine-java jdk13_v]$ sudo docker run jdk-13-musl/jdk-version:v1
openjdk 13-ea 2019-09-17
OpenJDK Runtime Environment (build 13-ea+16)
OpenJDK 64-Bit Server VM (build 13-ea+16, mixed mode)

Enter fullscreen mode Exit fullscreen mode

Building a HelloWorld application

Now we have a base container that we can use to create one with a Java app. Lets use a simple HelloWorld.java.

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

Enter fullscreen mode Exit fullscreen mode

Compile the Java code:

javac HelloWorld.java

Enter fullscreen mode Exit fullscreen mode

Having another Dockerfile for the app container:

FROM jdk-13-musl/jdk-version:v1
ADD HelloWorld.class /
CMD ["/opt/jdk/bin/java", "HelloWorld"]

Enter fullscreen mode Exit fullscreen mode

Building container:

sudo docker build .

Enter fullscreen mode Exit fullscreen mode

After tagging we can run HelloWorld:

sudo docker run jdk-13-musl/hello-world:v1
Hello, World

Enter fullscreen mode Exit fullscreen mode

The entire docker run takes around 600ms. Not bad for Java.

原文链接:Small Alpine Linux containers with Java

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容