{{announcement.body}}
{{announcement.title}}

Dockerizing a Spring Boot Application

DZone 's Guide to

Dockerizing a Spring Boot Application

Learn how to deploy Spring Boot application in Docker in easy way!

· Java Zone ·
Free Resource

We are in the world of developing applications using multiple languages, frameworks, architectures for each life cycle stage which creates enormous complexity. There is an urge to do container-based deployment. Spring Boot and Docker together is a great combo to develop a RESTful web service application. In this article, I will try to explain:

  • Docker and its benefits.
  • Creating a Spring Boot Application.
  • Hosting the Spring Boot Application in Docker.

Docker

Docker is an open-source technology used mostly for developing, shipping and running applications. The brilliance of Docker is that, once you package an application and all its dependencies into a Docker container, you ensure it will run in any environment. A Docker container image is a lightweight, standalone, executable package of software that has everything you need to run an application. For example, the creation of a Java application requires Java libraries, and when we deploy it on any system or VM, we need to install Java first. But, in a container, everything is kept together and shipped as one package, such as in a Docker container. Read the documentation for more information about Docker containers.

Spring Boot Application

Spring Boot is a microservice-based framework and making a production-ready application in it takes very little time. Developers can automatically configure their Spring application. However, Spring Boot is also capable of changing the configuration based on the dependencies you list. For example, when you list “MySQL” as a dependency, it will configure your Spring application with the “MySQL connector” included. There’s no need to deploy your application to a web server. You simply enter the run command to start the application. Let's see how to create a sample Spring Boot application.

Open Spring Starter to create a Java Maven application with Spring Starter libraries.

Spring Initializr

Provide the Artifact Group and Name, and in dependencies, add “Web” and leave everything else with the default, which will create a Maven project with Java and Spring Boot. This will generate a ZIP which is to be imported into IDE as a Maven project.

Hello world Spring Boot application

That is all!. Having imported the application, create a sample endpoint to check the functionality of the application.

Hello world Spring Boot application

Post running the application and accessing the endpoint in the browser, you will be able to see the result as below:

Initial output

The project structure will look like:

Spring Boot project structure

A brief overview of all files:

  • ApplianceController: Contains the business logic for all the Rest Endpoints.
  • ApplianceRepository: Responsible for providing CRUD operations on database tables.
  • ApplianceEntity: Specifies that the class is an entity and is mapped to a database table.
  • pom.xml: Contains all the dependencies required for the application.
  • application.properties: Used for configuring web properties and database configurations.
  • Dockerfile: Docker gives the user the capability to create their own Docker images and deploy them in Docker. To create your own Docker image, we have to create our own Dockerfile. Basically, a Dockerfile is a simple text file with all the instructions required to build the image
  • docker-compose.yml: Specifies which services/containers should be deployed and define how the images for the containers are built.
  • schema.sql: Contains the scripts to perform database operation.

Let's walk through by each classes:

HouseHoldApplication

This is a Spring Boot main class. A Spring Boot REST application loads through this class. We can also see that this class is created with the annotation @SpringBootApplication. As per the Spring documentation, the annotation @SpringBootApplication is equivalent to using @Configuration, @EnableAutoConfiguration, and @ComponentScan, and these annotations are frequently used together. Most of the time, in Spring Boot development, the main class is always annotated with all three of these important annotations. 

And we are going to modify the @SpringBootApplication (given below in the Java class) with a component path. Without that, the application cannot find out the controller classes.

Java
 




x
28


 
1
package com.user.household;
2
 
          
3
import org.springframework.boot.SpringApplication;
4
import org.springframework.boot.autoconfigure.SpringBootApplication;
5
import org.springframework.boot.autoconfigure.domain.EntityScan;
6
import org.springframework.cache.annotation.EnableCaching;
7
import org.springframework.context.annotation.ComponentScan;
8
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
9
import org.springframework.transaction.annotation.EnableTransactionManagement;
10
 
          
11
import javax.persistence.EntityListeners;
12
 
          
13
@SpringBootApplication
14
@EnableTransactionManagement
15
@EnableCaching
16
@ComponentScan(basePackages = {"com.user"})
17
@EntityScan("com.user.model")
18
@EnableJpaRepositories("com.user.repository")
19
public class HouseHoldApplication {
20
 
          
21
    public static void main(String[] args) {
22
 
          
23
        SpringApplication.run(HouseHoldApplication.class, args);
24
    }
25
 
          
26
}
27
 
          
28
 
          



ApplianceController

This class is responsible for creating RESTful endpoints necessary for the application and accessing the database with the help of a repository defined separately. The @RequestMapping annotation maps all HTTP operations by default and, in this application, it ensures that HTTP requests to /appliances/ are mapped to the getAllAppliances() method. As we are done with GET call, we need to implement RESTful POST call with the same path. 

The POST call enables the user to create an appliance or entry in the database. Similarly, we need to implement RESTful services for Update, Search, and Delete operations.

Java
 




xxxxxxxxxx
1
41


 
1
import org.springframework.web.bind.annotation.*;
2
 
          
3
import javax.validation.Valid;
4
import java.time.LocalDate;
5
import java.util.HashMap;
6
import java.util.List;
7
import java.util.Map;
8
 
          
9
@CrossOrigin(origins = "*", allowedHeaders = "*")
10
@RestController
11
@RequestMapping("/appliances")
12
public class ApplianceController {
13
 
          
14
 
          
15
    @Autowired
16
    private ApplianceRepository repository;
17
 
          
18
    /**
19
     * Get the entire list of appliances
20
     **/
21
 
          
22
    @GetMapping("/")
23
    public List<ApplianceEntity> getAllAppliances() {
24
 
          
25
        return repository.findAll();
26
 
          
27
    }
28
 
          
29
    /**
30
     * Create a new appliance
31
     **/
32
 
          
33
    @PostMapping("/")
34
    public ApplianceEntity createAppliance(@Valid @RequestBody ApplianceEntity appliance) throws RecordWithSameModelException, RecordWithSameBrandException {
35
 
          
36
 
          
37
        return repository.save(appliance);
38
 
          
39
 
          
40
    }
41
 
          



ApplianceEntity

This is the Appliance entity. Each entity must have at least two annotations defined: @Entity and @Id. The @Entity annotation specifies that the class is an entity and is mapped to a database table. The @Table annotation specifies the name of the database table to be used for mapping. The @Id annotation specifies the primary key of an entity and the @GeneratedValue provides for the specification of generation strategies for the values of primary keys.

Java
 




xxxxxxxxxx
1
82


 
1
package com.user.model;
2
 
          
3
import javax.persistence.*;
4
import java.time.LocalDate;
5
import java.util.Date;
6
 
          
7
@Entity
8
@Table(name="HOUSEHOLD")
9
public class ApplianceEntity {
10
 
          
11
 
          
12
    @Id
13
    @Column
14
    @GeneratedValue(strategy = GenerationType.IDENTITY)
15
    private Integer serialnumber;
16
 
          
17
    @Column(name="brand")
18
    private String brand;
19
 
          
20
    @Column(name="model")
21
    private String model;
22
 
          
23
    @Column(name="status")
24
    private String status;
25
 
          
26
    @Column(name="date")
27
    private LocalDate date;
28
 
          
29
 
          
30
    public ApplianceEntity() {
31
    }
32
 
          
33
    public ApplianceEntity(Integer id, String brand, String model, String status,LocalDate date) {
34
        super();
35
        this.serialnumber = id;
36
        this.brand = brand;
37
        this.model = model;
38
        this.status = status;
39
        this.date=date;
40
    }
41
 
          
42
    public Integer getSerialnumber() {
43
        return serialnumber;
44
    }
45
 
          
46
    public void setSerialnumber(Integer serialnumber) {
47
        this.serialnumber = serialnumber;
48
    }
49
 
          
50
    public LocalDate getDate() {
51
        return date;
52
    }
53
 
          
54
    public void setDate(LocalDate date) {
55
        this.date = date;
56
    }
57
 
          
58
    public String getBrand() {
59
        return brand;
60
    }
61
 
          
62
    public void setBrand(String brand) {
63
        this.brand = brand;
64
    }
65
 
          
66
    public String getModel() {
67
        return model;
68
    }
69
 
          
70
    public void setModel(String model) {
71
        this.model = model;
72
    }
73
 
          
74
    public String getStatus() {
75
        return status;
76
    }
77
 
          
78
    public void setStatus(String status) {
79
        this.status = status;
80
    }
81
}
82
 
          



ApplianceRepository

The @Repository annotation is used to define a repository. 

Java
 




xxxxxxxxxx
1
15


 
1
package com.user.repository;
2
 
          
3
import com.user.model.ApplianceEntity;
4
import org.springframework.data.jpa.repository.JpaRepository;
5
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
6
import org.springframework.stereotype.Repository;
7
import java.util.*;
8
 
          
9
import java.awt.print.Pageable;
10
 
          
11
@Repository
12
public interface ApplianceRepository extends JpaRepository<ApplianceEntity,Long>,JpaSpecificationExecutor<ApplianceEntity>{
13
    
14
}
15
 
          



schema.sql

This file is responsible for the creation of database entries.

SQL
 




xxxxxxxxxx
1
19


 
1
DROP TABLE IF EXISTS HOUSEHOLD;
2
 
          
3
CREATE TABLE HOUSEHOLD(
4
SERIALNUMBER SERIAL PRIMARY KEY NOT NULL,
5
BRAND VARCHAR(30) NOT NULL,
6
MODEL VARCHAR(30) NOT NULL,
7
STATUS VARCHAR(30) NOT NULL,
8
DATE DATE DEFAULT CURRENT_TIMESTAMP
9
);
10
 
          
11
INSERT INTO HOUSEHOLD(BRAND,MODEL,STATUS,DATE) VALUES('samsung','S100','active',NOW());
12
INSERT INTO HOUSEHOLD(BRAND,MODEL,STATUS,DATE) VALUES('samsung','S200','active',NOW());
13
INSERT INTO HOUSEHOLD(BRAND,MODEL,STATUS,DATE) VALUES('LG','L100','inactive',NOW());
14
INSERT INTO HOUSEHOLD(BRAND,MODEL,STATUS,DATE) VALUES('HITACHI','H100','active',NOW());
15
INSERT INTO HOUSEHOLD(BRAND,MODEL,STATUS,DATE) VALUES('samsung','S900','inactive',NOW());
16
INSERT INTO HOUSEHOLD(BRAND,MODEL,STATUS,DATE) VALUES('sony','SS100','active',NOW());
17
INSERT INTO HOUSEHOLD(BRAND,MODEL,STATUS,DATE) VALUES('OGENERAL','O100','active',NOW());
18
 
          
19
 
          



Having written all the business logic and framed the endpoints, we need to follow the below steps for creating JAR of the application.

  • mvn clean install
  • mvn clean package

As a result, a JAR is created as below:

JAR created

After creation of JAR,we need to dockerize the application by defining the below files:

Dockerfile

  • FROM openjdk:8 means this is a Java application and will require all the Java libraries. So it will pull all the Java-related libraries and add them to the container.
  • COPY copies the JAR generated by the application and add them to the container.
  • CMD specifies that this is a JAR and we need to run this JAR from within Docker.
Java
 




xxxxxxxxxx
1


 
1
FROM openjdk:8-jdk-alpine
2
COPY target/household-0.0.1-SNAPSHOT.jar /app/app.jar
3
CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar"]



docker-compose.yml

  • It contains keywords postgres and web, which defines services for web and database portions of the application.
  • The image keyword is used to specify the image from dockerhub for our postgres and web containers
  • For the database, we are using the ports keyword to mention the ports that need to be exposed for postgres.
  • Finally, we need to specify the environment variables for postgres, which are required to run postgres.
Java
 




xxxxxxxxxx
1
25


 
1
version: '3.2'
2
services:
3
  postgres:
4
    restart: always
5
    container_name: sample_db
6
    image: postgres:10.4
7
    ports:
8
      - '5432:5432'
9
    environment:
10
         - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
11
         - POSTGRES_USER=${POSTGRES_USER}
12
         - POSTGRES_DB=${POSTGRES_DB}
13
# APP**
14
  web:
15
    build: .
16
    environment:
17
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/test
18
    expose:
19
      - '8080'
20
    ports:
21
      - '8080:8080'
22
 
          
23
 
          
24
 
          
25
 
          



Now, we have arrived at a stage where we have the following:

  1.  Java – Spring Boot application
  2. Dockerfile that will create the image to be run in the Docker container.

To load these up in the Docker container, we have to first create the image and then run that image from the Docker container. We need to run certain commands in the folder that contains the Dockerfile.

This will create our image in Docker and load it up to the container.

Creating Docker image

We have successfully built the image that is ready to run as follows:

Image created

Yesss! The Spring Boot application is up and the server is running on port 8080.

Hitting api endpoint

The Spring Boot Application is running from the Docker container.

Here is the repository that contains the code for this article.

Please visit my below channel for a detailed explanation and subscribe.

https://youtu.be/GTj2gI4c8wQ

Topics:
cloud, docker, java, spring boot, spring boot application, tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}