/
2. Building pingme with a Dockerfile

2. Building pingme with a Dockerfile

Let’s start with the source code, it can be cloned down from git clone https://stream2stream@bitbucket.org/stream2stream/pingme.git

Once you have the code, navigate into the folder, execute the command

mvn package

To run the code enter

java -jar target/pingme.jar

To run the code you would simply execute the command java -jar target/pingme.jar again. But it will fail because pingme is already running on port 8080.

Without changing the code, there are two possible options

Create a container with java installed into it and copy the jar from the host into the running container, or build our own image that contains the app and everything needed to run our app.

Using a Java container and copying the jar into it

Begin by making sure you are still in the maven project directory for the pingme application - there should be a pom.xml file in the directory.

Execute the following commands

docker pull openjdk:alpine docker run -d --name openjdk:18-ea-11-alpine3.15 docker tag openjdk:18-ea-11-alpine3.15 openjdk:alpine11 docker run -dit -p 8080:8080 --name jdk openjdk:alpine11 cat docker cp ./target/pingme.jar jdk:/home/ docker exec -it jdk sh cd /home java -jar ./pingme.jar

Any images tagged with alpine is a lightweight version of the required image. This is a JDK 11 alpine version.

In your browser enter the URL localhost:8082/api/status, and you should a Healthy response back.

There are a lot of steps here to make this work, and any one of these could stop us from reaching our goal.

Line 3. creates an image in our registry called openjdk:alpine11. This is an easier name for us to work with.

Line 4. the cat command at the end stops the container from exiting, it’s waiting for keyboard input. Since it is running in detached mode (-d) as a daemon, the cat command will stop it from terminating (exiting).

Line 5. copies pingme.jar from the host into the container to the location /home.

Building our own image

An easier option than the above is to build your own image.

Building your own image can only take place if you know your applications runtime environment and the steps to ensuring that the environment is in place. This may require you to go through the steps above to ensure you have a good understanding the environment requirements. For example, using OpenJDK:alpine directly from hub.docker gives us the the wrong version of java (1.8), this is why we used the tag 18-ea-11-alpine3.15

A docker file (Dockerfile) is a template (cookie cutter) that is used to create images.

Docker images are constructed from image layers. This makes the whole image a more manageable component because the build tool is able to determine how much of an image needs to be changed/updated by looking at the differences between the layers. The other benefit is that when you pull an image from the registry, docker looks at the image layers and sees if any corresponding image layers already exist on your machine. If they do exist, then it only pulls those image layers that are necessary to give you a complete application image. So in our example, we pulled the openjdk:alpine image for our application and not the ubuntu image. If we had started with the ubuntu image, we would then need to install the required JDK manually.

Here is the Dockerfile we will be working with

Dockerfile reference can be found here

Each command in the docker will create an image layer. An excellent explanation of image layers can be found here.

Line 1. pull the initial layer required for our container environment

Line 3. Create a layer that creates a directory /home/java_app in the image

Line 5. Copy the file pingme.jar from the host folder ./target (this folder must be relative to where the docker build was run). The file is copied into the image folder /home/java_app

Line 7. Open port 8080 on the container

Line 9. When the container is running execute the command java -jar /home/java_app/pingme.jar

 

Build the file with docker build.

The docker build command will consume the Dockerfile (indicated by the last argument, the location of where the Dockerfile is, it must be a subdirectory from where the docker build is run). As it processes the file, docker build will check its cache to see if any of the statements are already available in its cache. If they are, they will be used to build the complete image. If they are not, the build process will build the image layer.

Once the image has been built, it can be used like any other image that you acquired using docker pull.

Be careful that you do not build your application in the Dockerfile. Docker build will only rebuild the image if the Dockerfile or things referenced in the host have changed. So any chnages in a git repo would not cause a rebuild.