By Subham Aggarwal | 7/4/2017 | General |Beginners

Spring Boot - Packaging and Deployment

Spring Boot - Packaging and Deployment

In this lesson, we will cover how to create a Spring Boot executable JAR and deploy our JAR as a Docker image. Docker is becoming insanely popular over time and this lesson will show you why!

 

An application is practically useless unless it is exposed to the world. Let us configure our Spring Boot app to be used over the cloud.

Making an executable JAR

Boot magic wouldn’t be complete without providing a good way to ship the entire app including all of its dependencies, resources, and so on in one composite, executable JAR. After the JAR file is created, it can simply be launched by running the following command:

java -jar <jar-name>.jar

 

Above command will run the JAR but there will a problem, as soon as you hit Ctrl (Cmd for Mac) + C, JAR will stop. For this, you can use slight modifications

java -jar <jar-name>.jar &

 

The ampersand(&) will ensure that the process doesn’t stop when you hit break.

 

  1. Let's go to our code directory, and execute ./gradlew clean build
  2. With the Uber JAR built, let's launch the application by executing java -jar build/libs/studentapplication-0.0.1-SNAPSHOT.jar
  3. This will result in our application running in the jar with the following console output:
.   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
 '  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::  (v1.3.0.BUILD-SNAPSHOT)
...
(The rest is omitted for conciseness)
...
2015-05-08 INFO: Registering beans for JMX exposure on startup
2015-05-08 INFO: Tomcat started on port(s): 8080 (http) 8443 (https)
2015-05-08 INFO: Welcome to the Student Catalog System!
2015-05-08 INFO: StudentRepository has 1 entries
2015-05-08 INFO: ExamRepository has 0 entries
2015-05-08 INFO: TeacherRepository has 1 entries
2015-05-08 INFO: Started StudentApplication in 12.156 seconds (JVM running for 12.877)
2015-05-08 INFO: Number of students: 1

Creating Docker images

The secret for Docker's overwhelming success lies behind the ability that it provides to package and deploy applications in a form of self-contained containers. The containers are much more lightweight than the traditional virtual machines. Multiple numbers of containers can be run on top of a single OS instance, thus increasing the number of apps that can be deployed on the same platform as compared to traditional VMs.

 

Making a Docker image and running it on a local development machine is workable, but not as exciting as being able to expose it to the world. We will need to publish it somewhere for it to be deployable, especially if we are thinking of doing it on Amazon or some other cloud-like environment. Luckily, Docker provides us with not only the Container solution, but also with a repository service, DockerHub, located at https://hub.docker.com where we can create repositories and publish our Docker images. So think of it like Maven Central for Docker.

 

Let’s follow some simple Gradle-related tasks that we can do to achieve this:

  1. To begin, we will create an account on DockerHub so that we can publish images.
  2. Once you have an account, we will need to create a repository named studentdocker.
  3. With this account created, now is the time to create the image. For this, we will use one of the Gradle Docker plugins. We will begin by modifying build.gradle to modify the buildscript block with the following change:
  4. buildscript {
     dependencies {
       classpath("org.springframework.boot:spring-boot-gradle-
         plugin:${springBootVersion}")
       classpath("se.transmode.gradle:gradle-docker:1.2")
     }
    }
  1. We will also need to apply this plugin by adding the apply plugin: 'docker' directive to the build.gradle file.
  2. Lastly, we will need to add the following Docker configuration to the build.gradle file as well:
  3. distDocker {
     exposePort 8080
     exposePort 8443
     addFile 
       file("${System.properties['user.home']}/.keystore"), 
         "/root/"
    }
  1. Assuming that Docker is already installed, we can proceed to create the image by executing ./gradlew clean distDocker.
  2. If everything has worked, you should see the following output:
$ ./gradlew distDocker
…
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar UP-TO-DATE
:findMainClass
:startScripts UP-TO-DATE
:distTar UP-TO-DATE
:distDocker
Sending build context to Docker daemon 30.46 MB
Sending build context to Docker daemon
Step 0 : FROM aglover/java8-pier
---> 69f4574a230e
Step 1 : EXPOSE 8080
---> Using cache
---> 725f1fd8c808
Step 2 : EXPOSE 8443
---> Using cache
---> d552630db9d5
Step 3 : ADD .keystore /root/
---> d0684cbd7fac
Removing intermediate container ef2dffe243f4
Step 4 : ADD ch6.tar /
---> a0963c837391
Removing intermediate container fb140e526e29
Step 5 : ENTRYPOINT /ch6/bin/ch6
---> Running in a769b6d6b40b
---> 778da2170839
Removing intermediate container a769b6d6b40b
Successfully built 778da2170839
BUILD SUCCESSFUL
Total time: 1 mins 0.009 secs

 

  1. We can also execute docker images command to see the newly created image:
$ docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             VIRTUAL  SIZE
ch6                          latest              778da2170839        17 minutes ago      1.04 GB
aglover/java8-pier   latest              69f4574a230e         11 months ago       1.01 GB

 

  1. With the image built successfully, we are now ready to start it by executing the following command:
docker run -d -P ch6

 

  1. After the container has started, we can query the Docker registry for the port bindings so that we can access the HTTP endpoints for our service. This can be done by the docker ps command. If the container is running successfully, we should see the following result (names and ports will vary):
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                                              NAMES
37b37e411b9e        ch6:latest          "/ch6/bin/ch6"      10 minutes ago      Up 10 minutes       0.0.0.0:32778->8080/tcp, 0.0.0.0:32779->8443/tcp   drunk_carson

 

  1. From this output, we can tell that the port mapping for the internal port 8080 has been set up to be 32778 (your port will vary for every run). Let's open http://localhost:32778/students in the browser to see our application in action.

 

When launching a Docker image, we used the –d and –P command-line arguments. Their uses are as follows:

  • -d: This indicates the desire to run the container in a detached mode where the process starts in the background.
  • -P: This instructs Docker to publish all the internally exposed ports to the outside so that we can access them.

 

Let's examine other instructions in detail:

  • The exposePort directive tells the plugin to add an EXPOSE <port> instruction to the Dockerfile so that when our container is started, it will expose these internal ports to the outside via port mapping. We have seen this mapping while running the docker ps command.
  • The addFile directive tells the plugin to add an ADD <src> <dest> instruction to the Dockerfile so that when the container is being built, we will copy the file from the source filesystem in the filesystem in the container image. In our case, we will need to copy the .keystore certificate file that we configured in one of our previous recipes for the HTTPS connector, which we instructed in tomcat.https.properties to be loaded from ${user.home}/.keystore. Now, we need it to be in the /root/ directory as, in the container, our application will be executed under root. (This can be changed with more configurations.)
By Subham Aggarwal | 7/4/2017 | General

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now