You’ve waded through the Docker tutorials, and now you’re ready to containerise your first Java application. Happy days.
But you’ve hit your first problem. You’re stuck on line 1 of your Dockerfile. You don’t know which parent image to use for your Java app:
FROM ... 🙁🙁🙁🙁 ?
What should you write here? There are thousands of Docker images available, so how do you know which is the best image to pick? Why should you choose one Docker image over another? Which images are safe to run in production? And which images need minimal configuration to get started?
If you’re asking these questions, then hello, this article is especially for you. By the end of this article, you’ll know the main images to choose from for Java apps, and I’ll give you a checklist to help you choose a good Docker parent image for your next project.
But before we start, let’s recap some of the basics.
What is a parent image in Docker?
A parent image is an image that Docker uses to run the instructions in your Dockerfile.
You can think of a parent image like the base layer of your Docker image. Some people call parent images base images.
A parent image usually has some software already installed inside it, such as the Java Runtime Environment (JRE), an application server like Tomcat or Wildfly, or maybe a web server like Apache or Nginx.
The idea is, you simply start with a parent image, throw in your application’s code (like a WAR file), and you have a Docker image, ready to go.
You can either create your own parent image, or use an existing image from someone else. Most people decide to use an existing image. In this article I’m going to focus on the choices available to you if you’re doing that.
So let’s look first at how you should pick a parent image.
What to look for in a parent image
When you’re out shopping for a parent image, here’s some questions you should really be asking:
Who maintains the image?
I think this is the most important one.
You can use an image which claims it is secure, but do you trust the person or company who makes the image?
On Docker Hub, there are over half a million images, and many of them are published by random developers. Would you want your app running on one of those images? It’s better to stick to official images, or images published by communities that you trust.
Is it secure, and is it updated regularly?
This is critical if you are running code in production. You need to choose an image which you know is going to be patched regularly for vulnerabilities.
Then when your parent image is updated, you’re going to want to trigger a re-build of your child image, so that you can be running your app with the latest updates.
On Docker Hub, you can use the Tags view to see when the most recent tags of an image were pushed. If the image hasn’t been updated in over a year, don’t use it.
(By the way, security doesn’t just go away just because you’re using containers. You still need to think about vulnerabilities and patching. This is especially important if you’re relying on a parent image that’s been published by somebody else. You need to be sure that they will keep it up-to-date.)
Does it include what you need?
If you’re running a standalone Java application (JAR), such as a Spring Boot application, then you’ll at least need to have a Java runtime installed inside the image. Usually this will be the JDK.
If an official image exists which comes preloaded with the software you need, it’s a good bet.
Is it lightweight?
This is the counterpoint to the previous question. Containers benefit from being lightweight. This makes them quicker to ship around between servers and start up.
Ideally you want your chosen parent image to contain everything you need, and nothing more. Of course that isn’t always possible; so try to pick an image that doesn’t contain a whole bunch of stuff that you don’t need.
Is it widely adopted by the community?
If you’re unsure which image to pick, have a look at which images are used as parent images in your favourite open source communities. Hop onto GitHub and see which images are referenced most commonly in Dockerfiles.
You shouldn’t always just follow the pack, but there is certainly strength in numbers, when you’re adopting technology.
Is it supported?
This is important if you’re running containers in an enterprise environment. In your company, you might have the requirement that you can only run software which has enterprise support.
In this case you should be careful about which image you pick. If a piece of software inside the container develops an issue, and you don’t have a way of getting the publisher to provide a timely fix, then you could have a problem.
So which image should you use?
I’ve gone through some of the questions to ask when choosing a parent image.
Now let’s look at the range of images out there to choose from.
If you’re developing an application that will run as a standalone Java application using
java -jar – this includes frameworks such as Spring Boot and Wildfly Swarm – then you’ve got a good choice of images you can use.
Here are some good choices for base images for standalone Java applications.
- OpenJDK (openjdk/openjdk)
- The official image for OpenJDK, the open source implementation of Java.
- As used in the official Spring Boot Docker example
- Has an Alpine Linux variant
- Has flavours for both Linux and Windows (tag
- JBoss Base JDK (jboss/base-jdk)
- A Java base image from JBoss
- includes OpenJDK
- Fabric8 JBoss OpenJDK (fabric8/java-jboss-openjdk8-jdk)
- Based on the JBoss Base JDK image, adding the tools below:
- Red Hat Java Application (registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift)
- An image designed to work with OpenShift
- Good for enterprise environments
- Designed to work with OpenShift
Your checklist for choosing an image
So in summary, choose an image that is:
- updated regularly with security patches
- published and maintained by a trusted, well-known source
- includes everything that your application needs, and little else
- matches your environment
- adheres to your enterprise standards, if you have them
My personal choice is to go with the Fabric8 JBoss JDK image for personal projects, and the Red Hat Java Application image for enterprise projects.
Which image did you go for? Do you have any other suggestions? Let me know in the comments below.