How to put your Java application into Docker container

Wojciech Krzywiec
8 min readApr 16, 2019

--

The main purpose of enormous popularity of Docker nowadays is that it’s really easy to use and it allows developers to create a portable application that could be run on every machine in a nick of time. With this blog post I would like to present how simple is to create your own Docker image with your own Java app inside.

Haven’t you heard of Docker yet? Or maybe you’re not comfortable with what exactly it is? Don’t worry, you can check my previous article in which I elaborate on that.

For demonstration purposes for this blog post I’ve created a simple Java project. It’s a Spring Boot app that connects to the NASA Astronomy Picture of the Day API, gets the picture of the current day with description and then prints it on a main page (HTML).

The source code of the application could be found on my GitHub account. And if you’re not familiar with Spring Boot, don’t worry. I won’t focus on its implementation, only Docker 🐋.

Creating and running the container

To start with that go to the root folder of your project (in my case ~/nasa-picture) and create a new text file called Dockerfile. It’ll contain all steps necessary to create an image (like steps in a food reciepe). For my application it looks like this:

FROM java:8-jdk-alpine
COPY ./build/libs/nasapicture-0.0.1-SNAPSHOT.war /usr/app/
WORKDIR /
usr/app
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "nasapicture-0.0.1-SNAPSHOT.war"]

Wow, what’s that even mean?! Some steps might be self-explanatory but let’s break all of them into smaller pieces.

  • FROM java:8-jdk-alpine— with this line we tell Docker that our image will be based on another image that is available on public repository (Docker Hub). This image was prepared by someone else and contains all necessary dependencies that we would need to run any Java application.
  • COPY ./build/libs/nasapicture-0.0.1-SNAPSHOT.war /usr/app/ — as you might already guess with this step we copy-paste something from one directory to another. But what and where? First argument after COPY is a path of an application that we want to put into container. I’m using .war file because my project is a web application, but you if yours is a standard .jar app go with that. The second parameter, /usr/app/ , is a directory in a container where we put the app.
  • WORKDIR /usr/app — here we instruct Docker to use /usr/app folder as a root, otherwise in each following command we would need to provide the full path to the resource.
  • EXPOSE 8080 — with it we inform Docker that a container will listen to specific port, the same as our app is using.
  • ENTRYPOINT ["java", “-jar", “nasapicture-0.0.1-SNAPSHOT.war"] — in the last command we tell Docker to run the application, where first value is a command and the last two are parameters.

Once we’ve got it we can go to the terminal, to a folder where Dockerfile is located and when you’re in there build an image with following command (the argument after -t flag is a name of an image, you can choose whatever you’d like; also notice that there is a dot . at the end of the command):

$ docker build -t nasa-picture .Sending build context to Docker daemon  35.54MB
Step 1/5 : FROM java:8-jdk-alpine
---> 3fd9dd82815c
Step 2/5 : COPY ./build/libs/nasapicture-0.0.1-SNAPSHOT.war /usr/app/
---> 6c90658d9558
Step 3/5 : WORKDIR /usr/app
---> Running in 3d453fe48248
Removing intermediate container 3d453fe48248
---> 27f352fbbb15
Step 4/5 : EXPOSE 8080
---> Running in 0c656ae718e7
Removing intermediate container 0c656ae718e7
---> b3bd82c446b6
Step 5/5 : ENTRYPOINT ["java", "-jar", "nasapicture-0.0.1-SNAPSHOT.war"]
---> Running in b09c6788d305
Removing intermediate container b09c6788d305
---> 08ee9123cd58
Successfully built 08ee9123cd58
Successfully tagged nasa-picture:latest

As you can see from above output, Docker is building the image by executing command step-by-step as they were defined in the Dockerfile.

Now we can check whether it was really built with following command:

$ docker imagesREPOSITORY    TAG          IMAGE ID        CREATED             SIZE
nasa-picture latest 08ee9123cd58 8 minutes ago 167MB
java 8-jdk-alpine 3fd9dd82815c 2 years ago 145MB

Great an image is available, so let’s run it:

$ docker run -p 3333:8080 nasa-picture

Yeah! Container has been created and it’s running, and to test it enter following URL in your browser — http://localhost:3333/

Now if you want to stop the application just use Ctrl + C combination on your keyboard. To inspect if it really is not running type the following:

$ docker container ls -a... IMAGE        COMMAND                STATUS           
... nasa-picture "java -jar nasapictu…" Exited (130) 7 seconds ago

Export Docker image to a file

Until this point everything was done on a single PC, but usually we would like to share our work with others and this would require to generate a file that could be sent via email, copied to Dopbox, fttp or so on. Docker allows to save an image as .tar file and to do so just type following command:

$ docker save --output nasa-picture-export.tar nasa-picture

First argument, with --output flag, is a name of an exported file and the latter is an image name that we put to a file.

As we now have an exported image you can share it and then to open it use following instruction:

$ docker load --input nasa-picture-export.tar

After that new image will be extracted and available to run (the same way as it was done previously).

Publishing image on Docker Hub

Previous method works fine, but let be honest. It’s not 21st century approach. We get used to be able to download everything from the Internet in the matter of seconds. Therefore exchanging files with Docker images might not to be the so convenient.

Instead we can push our image to the central repository, Docker Hub, and then be able to type it’s name in the console to fetch it wherever we are.

To do so first you need to have an account in Docker Hub. If you don’t have it create one, it’s free.

Then, after logging to your account, on a main page there will be an icon to Create arepository (see picture on the left). Click on it.

Next, a new page will show up where you can provide the name of the repository, its description and decide whether it will be a public (open to the world) or private (only you would see it) repository.

When everything is set up, just click Create button at the bottom of the page.

Now let’s back to the console on our PC and in it type following command in order to login to Docker Hub (during it it will prompt to provide the password):

$ docker login --username=wkrzywiec
Password:
WARNING! Your password will be stored unencrypted in /home/....
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded

Ok, so we’re connected. Now let’s prepare an image that will be pushed. I assume that you still have your image and to check it type:

$ docker images REPOSITORY               TAG                 IMAGE ID          
nasa-picture latest 430e1de8c0d4

We need add tag to an image. The tag usually contains useful information about a version of an image and it’s indicated with semi-columns after the image name, for example :latest

$ docker tag 430e1de8c0d4 wkrzywiec/nasa-picture:firsttry
  • 430e1de8c0d4 — it’s an id of an image that we would like to tag,
  • wkrzywiec/nasa-picture:firsttry — here we provide the full name of an image that will be sent to the Docker Hub. It matches certain patter — docker-hub-username/image-name:image-tag. It’s important to name it the same as it’s a Docker Hub repository. The tag can be whatever we want.

Everything is set up, so now let’s push it to the repository:

$ docker push wkrzywiec/nasa-picture
The push refers to repository [docker.io/wkrzywiec/nasa-picture]
e2fd04bd79f3: Pushed
a1e7033f082e: Mounted from library/java
78075328e0da: Mounted from library/java
9f8566ee5135: Mounted from library/java
firsttry: digest: sha256:a2c24d7e0abea09be2520e6bbf41b61f4be1da3f372a98fecc16ebb4db20fd07 size: 1159

It’s now in Docker Hub! To check it go to the website or you can pull the image in command line. If you go with second option first make sure that you don’t have this image locally with docker image prune -a. The you’ll be able to perform this:

$ docker pull wkrzywiec/nasa-picture:firsttry
firsttry: Pulling from wkrzywiec/nasa-picture
709515475419: Pull complete
38a1c0aaa6fd: Pull complete
5b58c996e33e: Pull complete
4eb443a91b8c: Pull complete
Digest: sha256:a2c24d7e0abea09be2520e6bbf41b61f4be1da3f372a98fecc16ebb4db20fd07
Status: Downloaded newer image for wkrzywiec/nasa-picture:firsttr

All right! It’s working! But what if you don’t want to provide the :firsttry tag whenever you need to pull an image? There’s nothing simpler, when you tag an image, as it was done in previous step, you need to tag it with :latest and then push it to Docker Hub. From now on to pull an image you can use docker pull wkrzywiec/nasa-picture .

If you would like to see the source of code of an application go check my GitHub project:

Or you can pull it’s Docker image:

--

--

Wojciech Krzywiec

Java Software Developer, DevOps newbie, constant learner, podcast enthusiast.