Spring Boot – Docker Deployment Cookbook

To deploy a Spring Boot application, we need to have a Docker running on our machine.

We can get it from here, quickly and easily:  https://www.docker.com/products/docker-toolbox

What is Docker?
Docker is a tool designed to make it easier to create, deploy, and run applications using containers. The key benefit of Docker is that it allows users to package an application with all of its dependencies into a standardized unit for software development.

Why do we need Docker?
Developers use Docker to eliminate “works on my machine” problems when collaborating on code with co-workers. Docker automates the repetitive tasks of setting up and configuring development environments so that developers can focus on building software. Docker makes it easy to share the application.

How does Docker work?
The docker technology uses the Linux kernel and features of the kernel like Cgroups and namespaces to segregate processes so they can run independently.

Docker provides an image-based deployment model. This makes it easy to share an application, or set of services, with all of their dependencies across multiple environments.

Docker image
An image is a lightweight, stand-alone, executable package that includes everything needed to run a piece of software, including the code, a runtime, libraries, environment variables, and configuration files.

Container
A container is a runtime instance of an image – what the image becomes in memory when actually executed.

In order to build an image, we need to define a dockerfile.

Dockerfile
A Dockerfile is a script, composed of various commands (instructions) and arguments listed successively to automatically perform actions on a base image in order to create (or form) a new one.

Docker deployment workflow explained

 

Here, we are going to deploy a Spring Boot application as an image using Docker. This application uses MySQL as the database. Before building the image for the application, we need to build a custom image for the MySQL database.

Building Custom MySQL image

To build a Custom MySQL image, we are going to follow the folder structure as shown below.

  1. Create a folder with name ‘Custom Image’, in that folder create another folder with name mysql. In mysql folder, place the dump file of the database of your application either with only structure of the database or including the data as per your requirements and name it as data.sql and add below two lines in the beginning of the script of dump file to create a database and use that database.
    CREATE DATABASE IF NOT EXISTS <your database name>;<br /><br />
    USE <your database name>;

    Give the name of your database in the above commands.
  2. Create a dockerfile with the following commands and name it as dockerfile and save it in a file format. Here, we are pulling the official mysql image and building our own custom image. Place it in mysql folder.
    FROM mysql:5.7
    RUN chown -R mysql:root /var/lib/mysql/ 
    ARG MYSQL_DATABASE 
    ARG MYSQL_USER 
    ARG MYSQL_PASSWORD 
    ARG MYSQL_ROOT_PASSWORD 
    ENV MYSQL_DATABASE=$MYSQL_DATABASE 
    ENV MYSQL_USER=$MYSQL_USER 
    ENV MYSQL_PASSWORD=$MYSQL_PASSWORD 
    ENV MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD 
    ADD data.sql /etc/mysql/data.sql 
    RUN sed -i 's/MYSQL_DATABASE/'$MYSQL_DATABASE'/g' /etc/mysql/dump.sql 
    RUN cp /etc/mysql/data.sql /docker-entrypoint-initdb.d
    
  3. Define .env file like this in the custom image folder.
    MYSQL_DATABASE=<your database name>
    MYSQL_USER=user
    MYSQL_PASSWORD=root
    MYSQL_ROOT_PASSWORD=root
    MYSQL_PORT=3306
    

    Give the name of your database as MYSQL_DATABASE.

  4. Then, define docker-compose.yml file as shown below. Use the args directive to define environment variables and set them from .env file. Place it in the Custom Image folder.
    version: '2'
    services:
    ### MySQL Container
       mysql:
           build:
                context: ./mysql
                args:
                   - MYSQL_DATABASE=${MYSQL_DATABASE}
                   - MYSQL_USER=${MYSQL_USER}
                   - MYSQL_PASSWORD=${MYSQL_PASSWORD}
                   - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
    ports:
               - "${MYSQL_PORT}:3306"
    
  5. Now, open the docker terminal, go to the Custom Image directory and execute the following command:
    docker-compose build
    The custom MySQL image is built now. Run docker images command and you can see the newly built image. The name of the image will be customimage_mysql

Building Image for Spring boot application

      1. In the Project root directory, create a Dockerfile with the following commands:
        FROM java:8
        ADD target/.jar  <your project jar_filename>.jar
        ENTRYPOINT ["java","-jar","<span style="font-weight: 400;"><your project jar_filename></span>.jar"]
        

        When you build your project, in the target folder a jar file will be created. You can specify the name of the jar in pom.xml by <finalName> tag.
        <br /><br />
        <strong><build></strong><br /><br />
        <strong><finalName>jar_filename</finalName></strong><br /><br />
        <strong></build></strong><br /><br />

      2. In the Project root directory, define your docker-compose file as shown below.
        version: '2'
        
        services:
          db:
            image: customimage_mysql
            restart: always
            ports:
            - "3306:3306"
              
          application:
           build: .
           ports:
             - "9111:9111"
           depends_on:
             - db
           links:
             - db
           environment:
             - database.url=jdbc:mysql://db/<span style="font-weight: 400;"><your database name></span>
        

        In the application service, specify the port number on which your application should run at ports and specify the same port number in your application.properties file of your Spring boot application.

        Give a name for your database in database.url variable which you specified in your custom MySQL image.

      3. Define the application.properties as shown below in the Spring boot project.
        The port number of the application given in docker-compose file should be same as server.port in application.properties.

        spring.datasource.url=${database.url}
        spring.datasource.username=root
        spring.datasource.password=root
        spring.datasource.driver-class-name=com.mysql.jdbc.Driver
        spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
        spring.jpa.hibernate.ddl-auto=update
        spring.jpa.generate-ddl=true
        spring.jpa.show-sql=true
        server.port=9111
        

        The port number of the application given in docker-compose file should be same as server.port in application.properties.

      4. Now, open the docker terminal, go to your project’s root directory location, build your maven project with the following command:
        mvn clean install
      5. After successfully building your maven project, build the image with the following command.
        docker-compose build
        A new image is created for your application. You can check with the docker images command.
      6. Now run your application using this command: docker-compose up
      7. Now your application is up and running. Open the browser and type this URL: http://<ip_address>:<port_number_of application>

    Example: http://192.168.99.100:9111

    192.168.99.100 is the docker terminal’s default IP address;
    9111 is the port number you mentioned in docker-compose file.

Pushing the Docker image to Registry(Docker Hub):

Docker Hub is a cloud-based registry service which allows you to link to code repositories, build your images and test them, stores manually pushed images, and links to Docker Cloud so you can deploy images to your hosts. It provides a centralized resource for container image discovery, distribution and change management, user and team collaboration, and workflow automation throughout the development pipeline.

  1. If you don’t have a Docker hub account, sign up for one at cloud.docker.com. Make note of your username and password.
  2. Log in to the Docker public registry on your local machine with the following command:docker login
     Login with your username and password.
  3. Tag the image using the following command:
    docker tag image_name username/repository:tag
    The tag is optional, but recommended, since it is the mechanism that registries use to give Docker images a version.
    Example: docker tag easy_pricing muralik/easy_pricing:1.0
  4. Push the tagged image to registry
    Docker push username/repository:tag
    Example:
    Docker push muralik/easy_pricing:1.0

Now the image is on public docker hub. You can pull that image from anywhere.