This article is originally published April 13th, 2017 at JaxEnter website: Link

In this tutorial you will learn how to write a Java EE application using two of the trendiest technologies: Spring Boot and Docker in NetBeans IDE.

Spring Boot is an innovative project that aims to make it easy to create Spring applications by simplifying the configuration and deployment actions through its convention over configuration based setup. Docker is an open source project that automates the deployment of applications inside software containers.

Today I’d like to make a tutorial in which a simple Spring Boot application is deployed using Docker.

Requirements

For this tutorial I will be using the Development build of NetBeans IDE, as the Docker integration will be in the next release of NetBeans.

image1

Grab the Java EE bundle from the download section.

Docker support

The Docker node is available in the Services window. To connect to a Docker instance, make sure that the Docker daemon is working.

On NetBeans go to the Services window:

image2

Next…

image3

After configuring the Docker instance, you can see all your images and containers, as well as the state of each container:

image4

The Docker integration in NetBeans supports many Docker operations such as running or pushing images, or starting and stopping containers:

image5

image6

Spring Boot support

I recently found a great Spring Boot plugin: NB-SpringBoot created by Alex Falappa

The features provided by the plugin:

  • Spring Boot new Maven project wizards:
    • Basic project
    • Project generated by Spring Initializr service
  • Enhanced properties file editor:
    • completion and documentation of configuration properties names
    • completion and documentation of configuration properties values (hints in configuration metadata)
  • Spring Boot file templates:
    • CommandlineRunner annotated classes
    • ApplicationRunner annotated classes
    • application.properties files
    • ConfigurationProperties annotated classes
    • additional-spring-configuration-metadata.json files
  • Spring file templates:
    • Component annotated classes
    • Configuration annotated classes
    • Service annotated classes
  • Spring MVC file templates:
    • Controller annotated classes
    • RestController annotated classes
  • Spring Data file templates:
    • interfaces extending Repository
  • Code generators in pom.xml files:
    • Add spring configuration processor dependency
    • Add spring-devtools & spring-actuator dependencies

Creating our Boot application

After installing the plugin, we can create a new project using the Spring Initializr directly from NetBeans:

image7

Next…

image8

Next, select the Spring Boot version and the needed dependencies.

image9

I just picked the Web and Actuator dependencies for my sample project.

Next…

image10

So now we have created our project base using Spring Initializer. The structure of the created project would be:

image11

Now we create a new RestController:

image12

The controller will be a classic “Hello World” Rest boundary:

1
2
3
4
5
6
7
8
@RestController
public class GreetingsController {
    
    @RequestMapping(path = "/time", method = GET)
    public String sayHelloWorld(){
        return "Hello World @ " + LocalTime.now();
    }
}

Run the project and go to http://localhost:8080/time to test the application:

image13

Another great feature of the SpringBootPlugin is the powerful code completion especially on properties files, decorated with the Javadoc of the suggested item:

image14

To deploy our application using Docker, we will need to prepare our container.

Now we need to build our first container, which will run our sample microservice. We do this by defining the Dockerfile, which is a text file containing series of commands that tell Docker how to build an image. Once we write a Dockerfile, we can then repeatedly build an image by running the docker build command.

In NetBeans, create the new Dockerfile:

image15

Create the “Dockerfile” in the “src/main/docker” folder.

image16

An example of a Dockerfile content that we can use :

1
2
3
4
5
6
FROM java:8
VOLUME /tmp
ADD nb-springboot-docker.jar app.jar
EXPOSE 8080
RUN sh -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

As you can see, the Dockerfile is very simple. It consists of the following instructions:

  • FROM – the FROM instruction specifies the starting image. In this example, it is the Java 8 image mentioned above. The first time you build this image, Docker will download the Java 8 image from the central Docker registry
  • VOLUME – define that a volume named /tmp should exist
  • MAINTAINER – this instruction simply specifies the author
  • ADD – this instruction copies the JAR file to the specified location in the image. Note that working directory for the dockerfile/java image is /data so that’s why we are putting the JAR file there.
  • EXPOSE – this instruction tells Docker that this server process will listen on port 8080
  • RUN – used to “touch” the jar file so that it has a file modification time (Docker creates all container files in an “unmodified” state by default). This actually isn’t important for the simple app that we wrote, but any static content (e.g. “index.html”) would require the file to have a modification time.
  • ENTRYPOINT – is the “what to run to ‘start’” command — we run Java, setting properties, for example, a quick additional property to reduce Tomcat startup time we added a system property pointing to “/dev/urandom” as a source of entropy, and then point it at our jar.

To build the image you can use some tooling for Maven (Spotify) or Gradle (Transmode).

For our example we will be using Maven.

Build a Docker Image with Maven

In the Maven pom.xml you should add a new plugin like this (see the Docker-Maven-Plugin documentation for more options):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.4.10</version>
    <configuration>
        <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
        <dockerDirectory>src/main/docker</dockerDirectory>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
    </configuration>
</plugin>

The plugin configuration is simple:

  • imageName: The name of the generated Docker image
  • dockerDirectory: The directory where you can find the Dockerfile
  • resources: The resources files to copy from the target directory to the Docker build (alongside the Dockerfile)

You can build an image with the configurations mentioned above by running this command:

1
$ mvn clean package docker:build

After the execution of the command, when you check the list of Docker images, you will discover that the built image is added to the list :

image17

 

There is also the java:8 image added to the list of images. This is because the nebrass/nb-springboot-docker is based on the java:8 image.

You can run the built image just by clicking the Run button.

image18

Next, configure your container :

image19

Next, configure the ports binding :

image20

A great feature is provided by NetBeans: « Add Exposed » will bind the exposed ports automatically in the created container.

By clicking the « Finish » button, the container will be launched, and a log window will appear in NetBeans to show you how your container is executed:

image21

Now, we check the application at http://192.168.99.100:8080/time

image22

Great ! This is working !

Next, we add a Maven Task that we will be used to run the container. It can be used for example to bind the task to some Maven Phase (package, deploy…).

The command line used to launch the container :

1
$ docker run –d –p 8080:8080 nebrass/nb-springboot-docker

So our Maven Task will execute the same command. We will use the exec-maven-plugin to launch the same command:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>DockerRun</id>
            <goals>
                <goal>exec</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <executable>/usr/local/bin/docker</executable>
        <arguments>
            <argument>run</argument>
            <argument>-d</argument>
            <argument>-p</argument>
            <argument>8080:8080</argument>
            <argument>${docker.image.prefix}/${project.artifactId}</argument>
        </arguments>
    </configuration>
</plugin>

So to run the container from Maven:

1
$ mvn exec:exec

The output:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
MacBook-Pro-de-Nebrass:nb-springboot-docker nebrass$ mvn exec:exec
[INFO] Scanning for projects...
[INFO]                                                                        
[INFO] ------------------------------------------------------------------------
[INFO] Building nb-springboot-docker 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- exec-maven-plugin:1.3.2:exec (default-cli) @ nb-springboot-docker ---
bf17bdaf0d9cb74e9fb94b20f9865d4424442413cd12a21804e252cce0976354
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.051 s
[INFO] Finished at: 2016-07-06T22:25:25+02:00
[INFO] Final Memory: 14M/245M
[INFO] ------------------------------------------------------------------------

The app now is deployed and running in the created Docker container and our Greetings service is accessible at http://DOCKER_HOST:8080/time (to see your running container docker ps)

The global Maven command that does the build, tests, creates the Docker image and runs it:

1
$ mvn clean install docker:build exec:exec

This is the command that I added to my NetBeans as custom Maven Goal:

image23

Next..

image24

The output in NetBeans:

image25

Summary

Congratulations! You have created a Spring Boot microservice that is executed and deployed in a Docker container which can be configured and managed in the same place where we handle the Spring Boot application.

The Spring Boot plugin developed by Alex Falappa is a great add-on and it’s worth trying it, you will love it for sure.