DevOps

Lean, Mean, Java Virtual Machine: Making Your Docker 7x Lighter With Alpine Linux

How to build a minimal JVM container with Docker on Alpine Linux?

There has definitely been an awakening of some kind. Lately we’ve been hearing more and more about Alpine Linux, a lightweight distro that’s rising in popularity mostly because of its Docker use case. A single Takipi support chat a few months back piqued our interest, and since then we see more and more of our users trying it out with their containers. In this post we’ll do a quick overview and walkthrough of Alpine and how you can use it to build lightweight Docker containers with Java or any other JVM language.

Let’s get started.

So what’s Alpine Linux anyway?

Alpine Linux is an independent stripped down flavour of Linux that’s based on musl libc (pronounce ‘muscle’) and busybox. Apart from being lightweight, it’s also security oriented and uses grsec/Pax which is a security enhancement to the Linux kernel. Simply having less packages and utilities that are otherwise added by default in other distributions also adds to its security.

In addition, Alpine uses its own package manager called apk which is fast and pretty straightforward to use. And Another cool perk is its run-from-RAM feature.

Alpine Linux on the rise – Google Trends
Alpine Linux on the rise – Google Trends

Does image size really matter?

Docker is all about minimalism BUT When it comes down to JVMs on Docker, the official Java Docker image would add up to over 800MB. This is a pain even if you’re not disk space sensitive because of two main reasons.

The bigger the image size, the longer it takes to:

  1. Build it
  2. Ship it over the network

When you’re dealing with tens and hundreds of containers, or constantly shipping updates, it enhances the negative effects of big image sizes so, yes, it matters. At the same time, an Alpine base image would only take 5MB of space.

Here’s a comparison from the gliderlabs/alpine image which serves as the source for the official docker-alpine image:

imagesize

Compared to Ubuntu which is probably the most popular distro for Docker users, that’s over a 37x improvement, saving up 183MB of disk space. With that said, Alpine is not for everyone and requires some digging around depending on your specific use case and the kind of features you’re expecting to get from your OS. If being clean and minimal is one of your biggest concerns, then by all means, you should check it out.

Alpine vs Ubuntu official Docker images: 1.1M pulls on alpine and 39.3M on ubuntu
Alpine vs Ubuntu official Docker images: 1.1M pulls on alpine and 39.3M on ubuntu

Getting started with Alpine: Check out the Alpine wiki with its practical comparison to other distros.

Super useful on Java

While not specific to Java use cases, using Alpine provides a huge size benefit when used together with a JVM on Docker. The out-of-the-box official java Docker image takes over 800MB, with Alpine, it can go down to 117MB if you’re only including the JRE on Java 8. That’s almost 7 times lighter! As for the actual installation, it depends on which version of Java you’re going for. Since Alpine uses musl libc, we have 2 options:

  1. OpenJDK installations work out-off-the-box with musl libc, here’s an example.
  2. Oracle HotSpot depends on glibc and requires an additional step.

The most popular dockerfiles for Oracle Java were published by frolvlad (9.3K pulls) and anapsix (6.9K pulls), including different configurations for minimal installations including glibc. Here’s one way to add glibc on Alpine:

RUN apk --update add curl ca-certificates tar && \
    curl -Ls https://circle-artifacts.com/gh/andyshinn/alpine-pkg-glibc/6/artifacts/0/home/ubuntu/alpine-pkg-glibc/packages/x86_64/glibc-2.21-r2.apk > /tmp/glibc-2.21-r2.apk && \
    apk add --allow-untrusted /tmp/glibc-2.21-r2.apk

On a sidenote, a nice little trick is viewing docker images through imagelayers.io. Here’s how the Java 8 image from anapsix looks like:

How to Install Takipi on Alpine Linux?

We first heard of Alpine following requests from users who wanted to monitor their JVMs with Takipi. To be able to run Takipi on Alpine we had to include a few more dependencies. Apart from glibc, we also require the zlib compression library, libstdc++ and the low-level runtime library libgcc. Hold on tight! Attached is a Dockerfile that describes all the required steps with comments. You’ll see how to install Java on Alpine with glibc, add the additional dependencies, install Takipi, and monitor a simple Scala server which has a few errors (btw, to learn more about what is Takipi, you can check out this page):

# Takipi
FROM alpine:3.2

MAINTAINER Chen Harel "https://github.com/chook"

# Install dependencies 
RUN apk --update add curl ca-certificates tar sqlite icu bash && \
    curl -Ls https://circle-artifacts.com/gh/andyshinn/alpine-pkg-glibc/6/artifacts/0/home/ubuntu/alpine-pkg-glibc/packages/x86_64/glibc-2.21-r2.apk > /tmp/glibc-2.21-r2.apk && \
    apk add --allow-untrusted /tmp/glibc-2.21-r2.apk

# Java version
ENV JAVA_VERSION_MAJOR 7
ENV JAVA_VERSION_MINOR 79
ENV JAVA_VERSION_BUILD 15
ENV JAVA_PACKAGE       jdk

# Download and unarchive Java
RUN mkdir /opt && curl -jksSLH "Cookie: oraclelicense=accept-securebackup-cookie"\
  http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.tar.gz \
    | tar -xzf - -C /opt &&\
    ln -s /opt/jdk1.7.0_79 /opt/jdk &&\
    rm -rf /opt/jdk/*src.zip \
           /opt/jdk/lib/missioncontrol \
           /opt/jdk/lib/visualvm \
           /opt/jdk/lib/*javafx* \
           /opt/jdk/jre/lib/plugin.jar \
           /opt/jdk/jre/lib/ext/jfxrt.jar \
           /opt/jdk/jre/bin/javaws \
           /opt/jdk/jre/lib/javaws.jar \
           /opt/jdk/jre/lib/desktop \
           /opt/jdk/jre/plugin \
           /opt/jdk/jre/lib/deploy* \
           /opt/jdk/jre/lib/*javafx* \
           /opt/jdk/jre/lib/*jfx* \
           /opt/jdk/jre/lib/amd64/libdecora_sse.so \
           /opt/jdk/jre/lib/amd64/libprism_*.so \
           /opt/jdk/jre/lib/amd64/libfxplugins.so \
           /opt/jdk/jre/lib/amd64/libglass.so \
           /opt/jdk/jre/lib/amd64/libgstreamer-lite.so \
           /opt/jdk/jre/lib/amd64/libjavafx*.so \
           /opt/jdk/jre/lib/amd64/libjfx*.so \
    && addgroup -g 999 app && adduser -D  -G app -s /bin/false -u 999 app \
    && rm -rf /tmp/* \
    && rm -rf /var/cache/apk/* \
    && echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf

# Set environment
ENV JAVA_HOME /opt/jdk
ENV PATH ${PATH}:/opt/jdk/bin	

### Takipi Installation 

# Takipi installer dependencies (we need xz for a future untar process)
RUN apk --update add xz

# Download required libraries libgcc_s.so.1, libstdc++.so.6
RUN curl -Ls https://www.archlinux.org/packages/core/x86_64/gcc-libs/download > /tmp/gcc-libs.tar.gz && \
	mkdir /usr/libgcc && tar -xvf /tmp/gcc-libs.tar.gz -C /usr/libgcc

# Download required libraries libz.so.1
RUN curl -Ls https://www.archlinux.org/packages/core/x86_64/zlib/download/ > /tmp/zlib.tar.gz && \
	mkdir /usr/zlib && tar -xvf /tmp/zlib.tar.gz -C /usr/zlib

# Register the new libraries (before starting the Takipi installation process)
RUN echo /usr/zlib/usr/lib >> /etc/ld.so.conf
RUN echo /usr/libgcc/usr/lib >> /etc/ld.so.conf
RUN /usr/glibc/usr/bin/ldconfig

# Starting the default run level to avoid errors while starting Takipi
RUN rc default

# Install Takipi
RUN curl -s /dev/null http://s3.amazonaws.com/get.takipi.com/takipi-t4c-installer | \
	bash /dev/stdin -i --sk=<SECRET_KEY>

# Register Takipi libraries
RUN echo /opt/takipi/lib >> /etc/ld.so.conf
RUN /usr/glibc/usr/bin/ldconfig

# We must add Takipi to the PATH so the agent be able to start Takipi by itself
ENV PATH ${PATH}:/opt/takipi/bin

### Takipi installation complete

# Get a Java tester app
RUN wget https://s3.amazonaws.com/app-takipi-com/chen/scala-boom.jar -O scala-boom.jar

# Running a Java process with Takipi
CMD java -agentlib:TakipiAgent -jar scala-boom.jar

Community

To dig in deeper into Alpine and get involved in its development you can check out their IRC channels on FreeNode: #alpine-linux and #alpine-devel where the core developers hang out. You can also join the mailing lists and forums.

From the comments we’re seeing on twitter, HN, and Reddit, the general sentiment is very positive and many Alpine users are seeing significant image size reductions, without compromising on other OS features. The numbers don’t lie, it’s gaining some serious momentum.

Final Thoughts

The benefits of using a full blown distribution sometimes just aren’t worth it when compared to a minimal OS like Alpine. Especially for the container use case. You might even call them… microcontainers.

We hope that this post helped you discover something new, and would be glad to hear your thoughts about it. Please feel free to use the comments section below.

Alex Zhitnitsky

Alex is an engineer working with OverOps on a mission to help Java and Scala developers solve bugs in production and rid the world of buggy software. Passionate about all things tech, he is also the co-founder & lead of GDG Haifa, a local developer group. Alex holds a B.Sc from the Technion, Israel's Institute of Technology.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button