Docker, Spring Boot, docker-compose.yml and publish to https//hub.docker.com

Share on:

This article is targeted for those who want to learn more about docker and How they can integrate Docker with their existing applications.

The base application we are going to take is a Spring Boot Application. The spring Boot application will be very simple with one Microservice for “Hello World”.

Contents

  1. Creating your first Spring Boot Application
  2. Create a very basic Docker Image and run the Spring Boot Application from Docker
  3. Finally, upload Spring Boot Docker Image to hub.docker.com
  4. Using docker-compose build and docker-compose up -d
  5. docker-compose stop and docker-compose rm
  6. Lab Session

GitHub Repo

Here is the github repository link for the project - https://github.com/rahulwagh/spring-boot-docker.git

Prerequisites

You do not need to be and expert on docker but fair bit of understanding on docker would be sufficient. But apart from that I would recommend the following -

  1. An IDE of your choice (Intellij, Eclipse, Atom, Sublime etc..)
  2. Docker installed on your system

1.Creating your first Spring Boot Application

The first step would be to create your Spring Boot Application. Spring Boot is very handy when it comes to bootstrapping, you can go to spring boot initializer (https://start.spring.io/) and fill in the basic information needed for creating Spring Boot Application.

Here are the details which I filled in -

  • Group - com.jhooq.demo
  • Artifacts - Jhooq-docker-demo
  • Project - Gradle Project
  • Packaging - Jar
  • Java - 11

In the next step, you need to add the dependencies for the REST web service.

Click on the ADD and search for **Spring Web(Build web, including RESTful, applications using Spring MVC. Uses Apache Tomcat as the default embedded container.)**

Once you have added the required dependencies, click on generate and then you can download your Spring Boot project.

The next step would be to import the complete project into IDE (I would recommend using Intellij or Eclipse).

After importing the project into Intellij it should look like this

But since we are going to create a very simple “Hello World” micro-service, so your web service controller should look like this

 1package com.jhooq.docker.ws;
 2
 3import org.springframework.web.bind.annotation.GetMapping;
 4import org.springframework.web.bind.annotation.RestController;
 5
 6@RestController
 7public class JhooqDockerDemoController {
 8
 9    @GetMapping("/hello")
10    public String hello() {
11        return "Hello - Docker";
12    }
13}</code>

Now after you are done with implementation of web-service, you need to build the complete project and since we are using Gradle then you can use the ./gradlew build task.

1$ ./gradlew build
1> Task :test
22020-09-01 12:01:55.189  INFO 8229 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
3
4BUILD SUCCESSFUL in 6s
55 actionable tasks: 5 executed

While building your spring boot project you should be watchful for BUILD SUCCESSFUL message. Because it tells you that you have build you project successfully.

Now after the successful build of your project now its time to check the jar file. So goto build/libs directory and look for the jar. In my case, the jar has been generated with the name -** _Jhooq-Docker-Demo-0.0.1-SNAPSHOT.jar_**

Verify your Spring Boot Web service

Alright now its time to verify your Spring Boot Microservice and for that you need to start your Spring Boot Application

1$ java -jar Jhooq-Docker-Demo-0.0.1-SNAPSHOT.jar

Since its a very small Spring Boot Application so it shouldn’t take more time to start but once it starts successfully then you should be able to see following message in the console logs

1Started JhooqDockerDemo in 5.039 seconds (JVM running for 5.239)

Lets verify our “Hello World” microservice

1$ curl http://localhost:8080/hello

It should return you back with

1Hello - Docker

If you reached till so far which means you are halfway through and now you can start Containerizing your spring boot application using Docker.

2. Create a very basic Docker Image and run the Spring Boot Application from Docker

Alright so to begin with Containerization you need to create a Dockerfile for your Spring Boot Application. Since its a very basic “hello world” application so we are going to keep our Dockerfile very minimalistic

1FROM openjdk:8-jdk-alpine
2ARG JAR_FILE=build/libs/*.jar
3COPY ${JAR_FILE} app.jar
4ENTRYPOINT ["java","-jar","/app.jar"]

So what we are trying to achieve here in this Dockerfile is -

  • Use openjdk 8 image - openjdk:8-jdk-alpine
  • Pick the spring boot jar from - build/libs/*.jar
  • Copy and rename the jar - app.jar
  • Define the entry point - [“java”,”-jar”,”/app.jar”]

3. Finally, upload Spring Boot Docker Image to hub.docker.com

Now we are pretty much ready with our Spring Boot application and its Docker image.

Step 1- Create an account on hub.docker.com

For uploading/publishing any image to hub.docker.com you must have an account on it.

Now after signup you need to Create Repository. After login, you should see the following screen where you can click on Create Repository

For this article we are going to create repository with the name **“jhooq-docker-demo”**

Step 2 - Build and tag Docker image

We need to be a little careful while building a docker image because we need to tag with the image with the same name.

1$ docker build -t jhooq-docker-demo .
 1Sending build context to Docker daemon  29.37MB
 2Step 1/6 : FROM openjdk:8-jdk-alpine
 3 ---> a3562aa0b991
 4Step 2/6 : ARG JAR_FILE=build/libs/*.jar
 5 ---> Using cache
 6 ---> 524b6f520504
 7Step 3/6 : COPY ${JAR_FILE} app.jar
 8 ---> Using cache
 9 ---> 1f36fca8ff57
10Step 4/6 : RUN mkdir destination-dir-for-add
11 ---> Using cache
12 ---> 2738ea541520
13Step 5/6 : ADD sample.tar.gz /destination-dir-for-add
14 ---> Using cache
15 ---> 0d33832e0b78
16Step 6/6 : ENTRYPOINT ["java","-jar","/app.jar"]
17 ---> Using cache
18 ---> f173aeaa6f10
19Successfully built f173aeaa6f10
20Successfully tagged jhooq-docker-demo:latest

Now we need to tag the image with docker hub registry name .i.e. rahulwagh17/jhooq-docker-demo

1docker tag jhooq-docker-demo rahulwagh17/jhooq-docker-demo:jhooq-docker-demo

Alright now we need to push the image to hub.docker.com. Refer to the following command for pushing the image

1docker push  rahulwagh17/jhooq-docker-demo:jhooq-docker-demo
1The push refers to repository [docker.io/rahulwagh17/jhooq-docker-demo]
274bb8b6f9582: Pushed 
335dadcae1f24: Pushed 
42eff7c27f0f5: Mounted from rahulwagh17/kubernetes 
5ceaf9e1ebef5: Mounted from rahulwagh17/kubernetes 
69b9b7f3d56a0: Mounted from rahulwagh17/kubernetes 
7f1b5933fe4b5: Mounted from rahulwagh17/kubernetes 
8jhooq-docker-demo: digest: sha256:7130c10e24fa94e55060e90977160d7e71483eaecf18f528c0f4a49ad30fe99a size: 1575

Here is screenshot after successful push

To verify that you have pushed your spring boot docker image successfully, you can login to hub.docker.com.

As you can see we have successfully pushed spring boot docker image to Docker Hub.

4. Using docker-compose build and docker-compose up -d

Before we go ahead and start digging into docker-compose there is a couple of question which might pop-up in your mind.

Why we need docker-compose when we have Dockerfile ?

What docker-compose do?

We will answer this question later but the first thing about docker-compose is not shipped along with the Docker. This means you need to install the docker-compose separately onto your machine based on the operating system you are using.

Here is the official docker-compose installation document from Docker

Since I am using Ubuntu, so this is how I installed it on my Ubuntu machine

For Ubuntu
1sudo apt  install docker-compose
Mac

There is Docker Desktop for Mac which can be download from here

Windows

For windows also there is Docker Desktop and it can be download from here

So now we have installed docker-compose, next we need to create docker-compose.yml

docker-compose.yml

 1version: '3'
 2
 3services:
 4  jhooq-springboot-container:
 5    image: jhooq-spring-boot-docker-compose:1
 6    build:
 7      context: ./
 8      dockerfile: Dockerfile
 9    volumes:
10      - /data/jhooq-springboot-container
11    ports:
12      - "8080:8080"</code></pre>
1. Understanding the docker-compose.yml
  1. services - We have defined service with the name jhooq-springboot-container
  2. Dockerfile - It is using existing Docker and the image build from it
  3. 8080:8080 - It’s port forwarding we are going to forward the docker container port to the host machine(ubuntu).
  4. volumes - In short, it’s a directory to save the image data and this directory can be used by multiple containers. In our case, we are going to create directory /data/jhooq-springboot-container and we are going to store the data for image - jhooq-spring-boot-docker-compose:1

Lets run some docker-compose commands on your terminal

2. Build and tag the image using docker-compose build
 1docker-compose build
 2```bash
 3
 4```bash
 5Building jhooq-springboot-container
 6Step 1/6 : FROM openjdk:8-jdk-alpine
 78-jdk-alpine: Pulling from library/openjdk
 8Digest: sha256:94792824df2df33402f201713f932b58cb9de94a0cd524164a0f2283343547b3
 9Status: Downloaded newer image for openjdk:8-jdk-alpine
10 ---> a3562aa0b991
11Step 2/6 : ARG JAR_FILE=build/libs/*.jar
12 ---> Using cache
13 ---> 524b6f520504
14Step 3/6 : COPY ${JAR_FILE} app.jar
15 ---> Using cache
16 ---> 9a77a2eb4a48
17Step 4/6 : RUN mkdir destination-dir-for-add
18 ---> Using cache
19 ---> 495906d31e45
20Step 5/6 : ADD sample.tar.gz /destination-dir-for-add
21 ---> Using cache
22 ---> 1fcfc28fa92a
23Step 6/6 : ENTRYPOINT ["java","-jar","/app.jar"]
24 ---> Using cache
25 ---> 348e0d3e7309
26Successfully built 348e0d3e7309
27Successfully tagged jhooq-spring-boot-docker-compose:1

As you can see from the logs we have successfully build the image and tagged it with - jhooq-spring-boot-docker-compose:1

3. Run the docker container using docker-compose up -d

After building the image successfully now you can run the container using the following command

1docker-compose up -d
1Creating network "jhooq-k8s_default" with the default driver
2Creating jhooq-k8s_jhooq-springboot-container_1 ... done

Now you can check the status of the container as well as the port on which it running

1docker ps -a
1CONTAINER ID        IMAGE                                COMMAND                CREATED             STATUS              PORTS                    NAMES
2794e4a93f514        jhooq-spring-boot-docker-compose:1   "java -jar /app.jar"   18 minutes ago      Up 18 minutes       0.0.0.0:8080->8080/tcp   jhooq-k8s_jhooq-springboot-container_1

As you can see your container is up and running using docker-compose commands.

Let’s test our microservice

1curl http://localhost:8080/hello
1Hello - Jhooq-k8s

Now we can answer our question - Why we need docker-compose when we have Dockerfile?

Answer -

  1. docker-compose is helpful when you want to create more than one container using the same docker-compose.yml
  2. docker-compose helps you to create multi-container application
  3. Using docker-compose you can spin desired number of containers but on the other hand it is not possible with simple Dockerfile
  4. It also helps you to define the volume so that volume can be shared by multiple containers.

Dockerfile - It will hep you manage single container docker-compose - You can manage multiple container using single docker-compose

5. docker-compose scale service

With docker-compose you can scale up the kubernetes services using the same docker-compose.yml. The only thing which you need to be careful is port number because once you start scaling up your services, you will need more ports to run your service.

So to overcome the problem of defining new ports for scaling up the service, docker-compose provides port ranges which can be defined in the docker-compose.yml

Here is docker-compose.yml with port range 8080-8100

 1version: '3'
 2
 3services:
 4  jhooq-springboot-container:
 5    image: jhooq-spring-boot-docker-compose:1
 6    build:
 7      context: ./
 8      dockerfile: Dockerfile
 9    volumes:
10      - /data/jhooq-springboot-container
11    ports:
12      - "8080-8100:8080"

Now you can easily scale up the service.

But before you scale up it is always recommended to build the image once again

1docker-compose build

Here is command to scale up the service

1docker-compose scale jhooq-springboot-container=2
1WARNING: The scale command is deprecated. Use the up command with the --scale flag instead.
2WARNING: The "jhooq-springboot-container" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash.
3Starting jhooq-k8s_jhooq-springboot-container_1 ... done
4Creating jhooq-k8s_jhooq-springboot-container_2 ... done

Now we have scaled up our service ”jhooq-springboot-container” and its running two containers on port 8080 and 8081.

5. docker-compose stop and docker-compose rm

After you are done with your container and you no longer need that container. So you can use stop and then remove the container.

Here the docker-compose commands which can be used -

1. Stop container using docker-compose stop
1docker-compose stop
1Stopping jhooq-k8s_jhooq-springboot-container_2 ... done
2Stopping jhooq-k8s_jhooq-springboot-container_1 ... done

As you can see it had stopped both the container

2. Remove the container using docker-compose rm

Here is the command to remove

1docker-compose rm
1Going to remove jhooq-k8s_jhooq-springboot-container_2, jhooq-k8s_jhooq-springboot-container_1
1Are you sure? [yN] y
1Removing jhooq-k8s_jhooq-springboot-container_2 ... done
2Removing jhooq-k8s_jhooq-springboot-container_1 ... done

Now we have removed all the container.

6. Lab Session

{#step-6}

Conclusion

What we have learned

  1. We started with a very basic Spring Boot Application with “Hello World” microservice
  2. Then we Dockerized the Spring Boot Application using Docker
  3. We used hub.docker.com to publish our first Spring Boot Docker Image
  4. Installed the docker-compose on the development machine
  5. Used docker-compose for Spring Boot Docker image
  6. Then used the docker-compose scaled service feature for scaling up the Spring Boot service
  7. Finally used docker-compose stop and docker-compose rm to stop and remove the container.

If you are interested more about DevOps and Kubernetes then please refer to my previous article on - Deploy Spring Boot microservices on kubernetes