Creating and deploying a Java 8 runtime container image

A Java runtime environment should be able to run a compiled source code while a development kit, such as a development kit, is running. OpenJDK contains all libraries/binaries to compile and run the source code. The latter is essentially a superset of the runtime environment. More details on OpenJDK support and lifecycle can be found here here,

Red Hat comes with Java OpenJDK 8 and 11 and includes media container images. More details can be found at here, If you use Red Hat middleware, the s2i images are also useful for deploying them to the Red Hat Openshift Container Platform, for example.

Note that Red Hat only provides OpenJDK-based Java 8 and 11 images. With that in mind, there will certainly be situations where developers want to build their own Java runtime images. For example, there could be such minimization of memory for the runtime image. Jolokio or Hawkular and even security parameters would also need to be set up. If you do not want to go into these details, I would recommend using the Red Hat container for OpenJDK.

In this article we will:

  • Create an image with Docker and Buildah.
  • We will be running on the localhost with Docker and Podman.
  • We will pass on our image to Quay.
  • Finally, we will have a problem Open Shift,

This article was written for OpenShift 3.11 and 4.0 Beta. Let’s get started right away.

Set up

To use our images and see how they work, we use a web app as part of our bundle. Recently, Microprofile.io has the MicroProfile Starter Beta to help you get started with MicroProfile by creating a downloadable package. Go out Microprofile.io and get the package for MicroProfile with Thorntail V2.

Retrieve the package for MicroProfile with Thorntail V2

Click the Download button to retrieve the archive file.

On my Red Hat Enterprise Linux (RHEL) computer, I first create a temporary directory, for example: demoappand de-archive the downloaded artifacts.

In my temporary directory, I do the following:

$ mvn clean compile package

Now we should have a demo app with a fat glass that we can call to run Thorntail.

Let’s copy that target/demo-thorntail.jar in the temporary directory.

Here is the Dockerfile with comments on each shift. The source code of this file can be found here GitHub.

# A Java 8 runtime example
# The official Red Hat registry and the base image
FROM registry.access.redhat.com/rhel7-minimal
USER root
# Install Java runtime
RUN microdnf --enablerepo=rhel-7-server-rpms 
install java-1.8.0-openjdk --nodocs ;
microdnf clean all
# Set the JAVA_HOME variable to make it clear where Java is located
ENV JAVA_HOME /etc/alternatives/jre
# Dir for my app
RUN mkdir -p /app
# Expose port to listen to
EXPOSE 8080
# Copy the MicroProfile starter app
COPY demo-thorntail.jar /app/
# Copy the script from the source; run-java.sh has specific parameters to run a Thorntail app from the command line in a container. More on the script can be found at https://github.com/sshaaf/rhel7-jre-image/blob/master/run-java.sh
COPY run-java.sh /app/
# Setting up permissions for the script to run
RUN chmod 755 /app/run-java.sh
# Finally, run the script
CMD ( "/app/run-java.sh" )

Now we have the Dockerfile Details, let us continue and build the picture.

An important point is that the Java OpenJDK runtime is packaged as “java-1.8.0-openjdk”. This does not include the compiler and others -devel Package.

The above Dockerfile based on RHEL, which means subscription-managerbecause the host has already attached the subscriptions.

Here are two ways to do it. If you run RHEL as I do, you can choose from the two binary files that will be deployed. Both should be there rhel7-server-extras-rpms,

You can activate this extras repo as follows:

# subscription-manager repos --enable rhel-7-server-extras-rpms

Create and run pictures locally

Create the image with docker:

$ docker build -t quay.io/sshaaf/rhel7-jre8-mpdemo:latest .

Start the picture with docker and localhost: 8080 points to container port 8080:

$ docker run -d -t -p 8080:8080 -i quay.io/sshaaf/rhel7-jre8-mpdemo:latest

We can also do that buildah Command used to create container images from a working container Dockerfile Gold from scratch. The resulting images are OCI compliant, so they can be used for any runtime that matches them OCI runtime specification (like Docker and CRI-O).

Build with buildah:

$ buildah bud -t rhel7-jre8-mpdemo .

Create a container with buildah:

$ buildah from rhel7-jre8-mpdemo

Now we can operate the container with Podman, which complements Buildah and Skopeo with a similar experience to the Docker command line: Allow users to run stand-alone (uncontrolled) containers. And Podman does not need a daemon to run containers and pods. Podman is also part of extras channel and the following command should execute the container.

$ podman run -d -t -p 8080:8080 -i quay.io/sshaaf/rhel7-jre8-mpdemo:latest

For more information about Podman, see Containers without daemons: Podman and Buildah in RHEL 7.6 and RHEL 8 Beta, and Podman and Buildah for Docker users.

After we have an image, we want to deploy it on OpenShift and test our app. For that, we need the oc Client libraries. I have my own cluster setup. You could choose to use the Red Hat Container Development Kit (CDK) / minishift Red Hat OpenShift Online or your own cluster. The procedure should be the same.

Deploy on OpenShift

For deployment in OpenShift, we need the following constructs:

  • An image stream for our newly created image container
  • Deployment configuration for OpenShift
  • Service and routing configurations

Image data stream

To create the image stream, the OpenShift Cluster should be able to retrieve the container image from somewhere. So far, the image was on my own computer. Let us push it quay, The Red Hat Quay Container and the Red Hat Quay application enable secure storage, distribution, and provision of containers in every infrastructure. It is available as a stand-alone component or in conjunction with OpenShift.

First, I have to sign in to Quay, which I can do as follows:

$ docker login -u="sshaaf" -p="XXXX" quay.io

And then we push our newly created image to Quay:

$ docker push quay.io/sshaaf/rhel7-jre8-mpdemo

Let’s take a look at the constructs before we deploy them. For the timid, you can skip the details in the deployment template and move on to the project creator.

Now we have the picture, we define our stream:

- apiVersion: v1
kind: ImageStream
metadata:
name: rhel7-jre8-mpdemo
spec:
dockerImageRepository: quay.io/sshaaf/rhel7-jre8-mpdemo

Again, you can see our point of view directly in our image archive on Quay.io.

Deployment Configuration

Next is the deployment configuration that sets up our pods and triggers, pointing to our newly created stream, and so on.

If you are unfamiliar with containers and OpenShift deployments, you should consult them ebook,

- apiVersion: v1
kind: DeploymentConfig
metadata:
name: rhel7-jre8-mpdemo
spec:
template:
metadata:
labels:
name: rhel7-jre8-mpdemo
spec:
containers:
- image: quay.io/sshaaf/rhel7-jre8-mpdemo:latest
name: rhel7-jre8-mpdemo
ports:
- containerPort: 8080
protocol: TCP
replicas: 1
triggers:
- type: ConfigChange
- imageChangeParams:
automatic: true
containerNames:
- rhel7-jre8-mpdemo
from:
kind: ImageStreamTag
name: rhel7-jre8-mpdemo:latest
type: ImageChange

The service

Now that we have the deployment, we also want to define a service that ensures internal load balancing, IP addresses for pods, and so on. Service is important if our newly created app should finally be exposed to other traffic.

- apiVersion: v1
kind: Service
metadata:
name: rhel7-jre8-mpdemo
spec:
ports:
- name: 8080-tcp
port: 8080
protocol: TCP
targetPort: 8080
selector:
deploymentconfig: rhel7-jre8-mpdemo

The street

And the last part of our mission is the road. It’s time we took the road to the outside world. We can define which internal service this route refers to. OpenShift helps you make the most of your Java 8 runtime deployment.

- apiVersion: v1
kind: Route
metadata:
name: rhel7-jre8-mpdemo
spec:
port:
targetPort: 8080-tcp
to:
kind: Service
name: rhel7-jre8-mpdemo
weight: 100

The full template for the above can be found here on GitHub,

Let’s also create a project in OpenShift as follows:

$ oc new-project jredemos

And now we have the Java 8 runtime on OpenShift. To do this, run the following command:

$ oc process -f deployment.yaml  | oc create -f -

This will create the entire deployment, and you should be able to see it:

Results of the creation of the entire deployment

Now execute the following command:

$ oc get routes

This shows the routes as follows:

The streets

Let’s copy the road to our browser and we should see that the web app is running on RHEL 7 with the Java 8 runtime. (The following address is specific to the cluster test and will be another cluster.)

http://rhel7-jre8-mpdemo-jredemos.apps.cluster-1fda.1fda.openshiftworkshop.com/

Summary

We have successfully created a Java 8 runtime container image with Docker or Buildah. Please pay attention to the following:

  • It is important to note that this picture shows how it can be done; It does not contain things like Jolokio or Hawkular that might be required for deployments.
  • In addition, the parameters required to run Java apps in containers are not taken into account, which is well explained in this article by Rafael Benevides.
  • Also, always consider the support and lifecycle policy when deploying your own container images hereIf you are running Red Hat’s build from OpenJDK.

We then provided this with our basic MicroProfile demo app from OpenShift MicroProfile Starter Beta,

If you want to build a more complete demo application, consider the following resources:

The full resources for this article can be found here here,

 

Leave a Reply

Your email address will not be published. Required fields are marked *