Build a Java 8 Spring Boot App with Docker

Build a Java 8 Spring Boot App with Docker

Build a Java 8 Spring Boot App with Docker - In this article, I am going to show you how to develop and run a simple Spring web application using Java 8 without installing Java 8 on your local machine.

Python developers use virtual environments for creating and managing separate environments for different projects, and each using different versions of Python for execution and storing and resolving Python dependencies. Java and many other technologies do not support a virtual environment concept. At this point, Docker comes to our aid.

Docker is a virtualization platform. I am not going dive into details of docker's details. you can find basic information and installation guide from the docker official site.

Once you have the Docker toolbox installed, you do not need install Java 8 or MySQL which are needed in our sample application.

Now, you can download my codes from GitHub.

First, let's check the Docker-compose file:

version : '2'

      context: . 
      dockerfile: springapp.dockerfile
      - "8080:8080"
      - net-spring-db
      - .:/vol/development
      - mysqldbserver

      context: . 
      dockerfile: mysqldb.dockerfile
      - "3306:3306"
      - net-spring-db
      MYSQL_DATABASE: testdb
      MYSQL_USER: myuser
      MYSQL_PASSWORD: mypassword
      MYSQL_ROOT_PASSWORD: myrootpassword
    container_name: mysqldbserver

    driver: bridge

We have two servers each on the 'net-spring-db' network. The first one is named 'springappserver' and configured with the springapp.dockerfile, which will be described later. The second one is named as mysqldbserver and configured with the mysqldb.dockerfile, which will be described later.

Now, let's have a look at the springapp.dockerfile:

# Java 1.8 & Maven Dockerfile

# pull base image.
FROM java:8

# maintainer
MAINTAINER Dursun KOC "[email protected]"

# update packages and install maven
RUN  \
  export DEBIAN_FRONTEND=noninteractive && \
  sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \
  apt-get update && \
  apt-get -y upgrade && \
  apt-get install -y vim wget curl maven

# attach volumes
VOLUME /vol/development

# create working directory
RUN mkdir -p /vol/development
WORKDIR /vol/development

# maven exec
CMD ["mvn", "clean", "package", "exec:java"]

This Docker file configures a Docker image, which is inherited from a Java 8 image from Docker Hub. Over that Java 8 image, I have installed vim, wget, curl, Maven, and set the volume in order to put my existing projects code. And finally, execute the Maven command to run my application.

Now let's check the mysqldb.dockerfile:

FROM mysql/mysql-server

MAINTAINER Dursun KOC <[email protected]>

# Copy the database initialize script: 
# Contents of /docker-entrypoint-initdb.d are run on mysqld startup
ADD  mysql/ /docker-entrypoint-initdb.d/

This Dockerfile configures a Docker image, which is inherited from the MySQL/mysql-server image from Docker Hub. Over the MySQL image, I put my db-schema creation scripts, which are located in the MySQL folder. I have a single SQL file at this folder — data.sql — in order to create the 'person' table.

Now, let's see application structure.

Our application is started from the src/com/turkcell/softlab/ file, and our only Controller is the PersonController(src/com/turkcell/softlab/controller/

You can run the whole project with a simple command:

docker-compose up -d

For testing, use the following two commands in your local machine:

  • Create new person:
curl -H "Content-Type: application/json" -X POST -d "{\"first\": \"Mustafa\",\"last\": \"KOÇ\",\"dateofbirth\": 381110400000,\"placeofbirth\": \"Erzincan\"}" ""
  • List existing people in the database:
curl -H "Content-Type: application/json" -X GET ""

Now, it's your turn! You can dive deeper into Java 8 and Spring Boot using this template.

Deploying a Spring Boot Application with Docker

Deploying a Spring Boot Application with Docker

Deploying a Spring Boot Application with Docker. Learn how to package a Spring Boot application as a Docker container. Add Docker to Your Spring Boot Application. How to leverage Docker to deploy your Spring Boot application. Docker enables you to deploy a server environment in containers. Deploying your Spring Boot app as a Docker container is not hard, and can alleviate a lot of problems that you may encounter when moving your app around the multiple environments it has to go, like development machines, QA environment, staging, and production.

Docker enables you to deploy a server environment in containers. A container is a standardized unit of software that assembles code, runtime, dependencies, settings, and initialization in a single package that you can run reliably from one computing environment to another. Deploying your app as a Docker container is not hard, and can alleviate a lot of problems that you may encounter when moving your app around the multiple environments it has to go, like development machines, QA environment, staging, and production.

In this tutorial, you’ll see how to leverage Docker to deploy your Spring Boot application.

First, let’s build a sample Spring Boot app to use.

Create A Spring Boot App

You’ll use Spring Initializr to generate your Spring Boot project with the help of HTTPie, a simple command-line HTTP client.

You may use the Spring Initializr website directly if you don’t want to use the command line.

From the command line simply enter:

http \
 dependencies==web,okta \
 groupId==com.okta.spring-docker.demo \
 packageName==com.okta.spring-docker.demo \

And then unzip the downloaded file.

unzip -d spring-boot-docker
cd spring-boot-docker

You’ll next add a web controller by creating file src/main/java/com/okta/springdocker/demo/

package com.okta.springdocker.demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

public class WebController {

    public String home() {
        return "Welcome!";

You also need to configure the security settings for this project. For the moment, you’ll want to allow all requests, so update your file to the following:

package com.okta.springdocker.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;

public class DemoApplication {

    public static void main(String[] args) {, args);

    static class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        protected void configure(HttpSecurity http) throws Exception {

You may compile and run your app with:

./mvnw package
java -jar target/demo-0.0.1-SNAPSHOT.jar

Then if you hit [http://localhost:8080](http://localhost:8080) you should see a "Welcome!" message.

Run Your Spring Boot App as a Docker Container

To run your app as a Docker container, the very first step is to install Docker.
After installing, it’s time to build your container. For that, Docker uses a file that describes how to assemble the container, which is called a Dockerfile. The Dockerfile consists of step-by-step instructions to execute in a container.

For your Spring Boot app, you’ll use a simple Dockerfile file:

FROM openjdk:8-jdk-alpine (1)

COPY target/demo-0.0.1-SNAPSHOT.jar app.jar (2)

EXPOSE 8080  (3)

ENTRYPOINT ["java", "-jar", "/app.jar"] (4)

| 1 | You’ll start your Dockerfile with a FROM declaration that defines a source container image to build upon. In this way you can leverage an existing container definition that contains JDK 8. |
| 2 | The second instruction is COPY. Here you are telling Docker to copy a local file into the container, in this case, your built application will be available in the container as /app.jar. |
| 3 | The EXPOSE part shows you that the app will listen on port 8080. Although it is not required to make the Docker container work properly, it acts as documentation for future readers. |
| 4 | The last command, ENTRYPOINT, tells Docker what it should execute when you run that container. As you are building a Spring Boot application, this is a simple java -jar of your app. |

Now you can build the container on your command line. Execute the following while replacing okta:spring_boot_docker with a tag of your liking, it will serve as a name to reference the container you are building:

docker build . -t okta:spring_boot_docker

If all went well, you may now run your Dockerized app (using the same tag as you used before):

docker run --publish=8080:8080 okta:spring_boot_docker

To stop the container, hit CTRL-C. Verify the container isn’t running, execute:

docker ps

This will list all the containers running on your machine. If your Spring Boot app is still running, you can terminate the container with (use the Container ID printed by docker ps):

docker kill <CONTAINER_ID>

As your JAR file is copied into the container when you build it, you will need to rebuild your container each time you want to use a newer version of the app. So the cycle would be:

  1. Change your code

  2. Build the app ./mvnw package

  3. Build the container docker build . -t okta:spring_boot_docker

  4. Run the container docker run --publish=8080:8080 okta:spring_boot_docker

  5. Stop the container

  6. Loop

Now you know the basics of using Docker containers to run your app! In the future, you can publish your built container into Docker registries (like DockerHub), so others can fetch the container and it’ll be ready to run.

Next, we will secure the app with Okta and understand how we can pass sensitive data to the container.

Secure Your Spring Boot and Docker App

You’ll need a free developer account with Okta. Okta is a SaaS (software-as-service) identity management provider. We make it easy to add features like single sign-on, social login, and OAuth 2.0 to your application. Sign up for an account on our website if you haven’t already.

Complete the steps below to create an OpenID Connect (OIDC) app.

  1. Log in to your developer account at

  2. Navigate to Applications and click on Add Application

  3. Select Web and click Next

  4. Give the application a name (.e.g., Java Spring Boot Docker)

  5. Add the following as Login redirect URI: [http://localhost:8080/login/oauth2/code/okta](http://localhost:8080/login/oauth2/code/okta)

  6. Click Done

Okta requires some properties to work correctly, we will send those through Docker as environment variables.

Change the DemoApplication class, replacing .authorizeRequests().anyRequest().permitAll() with .authorizeRequests().anyRequest().authenticated(). This will tell Spring that all the endpoints of your app will require an authenticated user.

protected void configure(HttpSecurity http) throws Exception {

Let’s give it a try!

First compile and build your container. For the build process to work correctly, you will need to provide your Okta information as part of the command line, replacing <org_url>, <client_id> and <client_secret>. You will find those values in your Okta account. The org_url is shown at the top right corner of the dashboard. The client_id and client_secret are shown in your app settings.

./mvnw package

Then build the container:

docker build . -t okta:spring_boot_docker

In order to run the container now, you will pass your Okta info to the container as environment variables. This is done by using the -e command line parameter. Like so:

docker run --publish=8080:8080 \
 -e OKTA_OAUTH2_ISSUER=<org_url>/oauth2/default \
 -e OKTA_OAUTH2_CLIENT_ID=<client_id> \
 -e OKTA_OAUTH2_CLIENT_SECRET=<client_secret> \

Now if you hit [http://localhost:8080](http://localhost:8080) you will see a login form, and after providing your username and password you should be able to see the welcome page again. A dependency and a couple of properties are it takes to secure your application with OIDC/OAuth 2.0!

How to implement CI/CD into Spring-Boot-based Java Applications?

How to implement CI/CD into Spring-Boot-based Java Applications?

You'll learn how to implement CI/CD on a Spring Boot Java app using Maven, GitHub, Travis CI, Docker, Codecov, SonarCloud, and Heroku.

I am very excited to share my experiences building Continuous Integration/Continuous Delivery (CI/CD) into Spring-Boot-based Java applications. First, let's establish everything we will learn in this tutorial:

Step 1) Create a Spring Boot Java App using Spring Initializr

Step 2) Create a GitHub repository

Step 3) Use Travis CI and Docker to implement CI/CD

Step 4) Add Codecov to provide code coverage

Step 5) Use SonarCloud to write stellar code

Step 6) Build a project site using GitHub site-maven-plugin

Step 7) Deploy the app on Heroku using heroku-maven-plugin

Step 8) Manage topics

Gradually, we'll add badges to the file so that we can be notified in real-time on the state of Travis CI, Docker, Codecov, and SonarCloud. Also, we'll add the license badge.

Are you ready? If not take time to better understand or prepare yourself and continue to read this later. The code is available here. So just fork, it's all yours!

Step 1: Create a Spring Boot Java App Using Spring Initializr

In this project, I used Spring Tool Suite 4 (STS 4) IDE; you are free to use whatever tool you find suitable for this project. STS 4 has the Spring Initializr built-in, so that's why I chose it for this project.

This is what STS 4 dark theme looks like:

Click on File -> New -> Spring Starter Project

You will get:

Please fill out the form as follows:

Name: cicd-applied-to-spring-boot-java-app

Group: com.cicd

Artifact: cicd-applied-to-spring-boot-java-app

Description: Implementing CI/CD on Spring Boot Java App

Package: com.cicd.cicd-applied-to-spring-boot-java-app

By default:

Type: Maven

Packaging: jar

Java Version: 8

Language: Java

You will get:

![STS 4 - Form completed]( - Form completed")

Then, click Next.

Click on Spring Web:

![STS 4 - Spring Web]( - Spring Web")

Click on Finish. The new project will appear:

Next, please open the file.

We can then add a basic endpoint:

Right click -> Run As -> Maven build

Then you will receive:

To run the app, please add the following:

Goals -> spring-boot:run

Click Run:

The final result can be found here: http://localhost:8080/

Now, on to the next step!

Step 2: Create a GitHub Repository

First, you need to sign in or sign up. I'm already a GitHub user so I just signed in. You will be directed to the homepage:

To create a new repository, click on green button "**New" **or click here. You will then be directed here:

Please fill out the form as follows:

Repository name: cicd-applied-to-spring-boot-java-app (I chose to set the same name as the artifact field from step one)

Description: Implementing Continuous Integration/Continuous Delivery on Spring Boot Java App

Click on Public

Click on Initialize this repository with a README

Select the MIT license.

Why? It's very simple. The following links are helpful to better understand why you need an MIT license. Here's how to choose an open-source license and how open-source licenses work and how to add them to your projects.

Later, we'll add the .gitignore file.

Then, click on Create repository:

This is the new repository:

I suggest you add a file named Why? While working on a project, you may face difficulties and need to ask for help. The goal is to save time when solving problems or fixing bugs.

To create it, please click on Create new file:

Then, fill the name field with and edit the file as follows. CI/CD is an example of research and the links represent results. "##" makes bold text.

Furthermore, click on the green button "**Commit new file" **at the bottom of the page:

This is what we get:

Now, please install Git (Git installation can be found here) and GitHub Desktop (GitHub Desktop installation can be found here).

After installing these two tools, it's time to clone the project we started in step one.

Open GitHub Desktop and select the repository we created previously as follows:

Click on File -> Clone repository...:

You'll get this pop-up:

Just fill the search bar with "cicd;" you will find the repository: "cicd-applied-to-spring-boot-java-app" among the results:

Select the repository and click on Clone:

GitHub Desktop is cloning the repository:

The repository is already cloned:

At this stage, open the repository folder. This is my path:

My repository folder contains three files: LICENSE,, and shown below:

It's time to open the folder where the code is saved:

Copy the content from the code folder and paste it into the repository folder. The repository folder looks as follows:

It's important to ignore files and folders. We will not directly modify these files when working on a project. In order to do that, we'll make some changes to the .gitignore file from the repository folder. I used Sublime Text to edit that file.

Here's what it should look like before any changes:

Here's what it will look like after making changes.

First, add: .gitignore. It should look like:

Now, this is what folder repository looks on GitHub Desktop:

Fill the summary field with "First Upload" and click "Commit to master":

So what's next? Click on Push origin:

The repository is now up-to-date on GitHub:

Step 3: Use Travis CI and Docker to Implement CI/CD

Note: If you're not familiar with either of these tools, check out this Travis CI Tutorial and Docker Getting Started tutorial to help you get started.

Sign up or sign in with GitHub and make sure Travis CI has access to your repository. Then, create a file named .travis.yml, which contains instructions that Travis CI will follow:

At first, this is what I get:

Then, click on .travis.yml file:

This is the repository on Travis CI:

Now, we'll add a Travis CI badge so that we are notified about changes, etc.

To edit the file, please click on the pencil icon:

We'll get this page:

Add this text but replace "FanJups" with your Travis CI username:

Then, add a commit description "Adding Travis CI badge" and click on the Commit changes button:

Then, we get:

It's important to know that, for every change you make, Travis CI will trigger a build and send an email. It's a continuous process:

We successfully added Travis CI and its badge. Next, we'll focus on Docker.

First, sign in or sign up on Docker Hub:

Click on the Create Repository button:

Fill out the form as follows:

Name: cicd-applied-to-spring-boot-java-app (GitHub repository name)

Description: Implementing Continuous Integration/Continuous Delivery on Spring Boot Java App (GitHub repository description)

Visibility: choose Public

Build Settings: select GitHub

After clicking on the Create button:

It's time to link our Docker repository to our GitHub repository. Click on Builds:

Then, click on Link to GitHub:

Select your GitHub repository:

Now that the GitHub repository is selected, we need to make some changes:

Autotest: select Internal and External Pull Requests

Repository links: select Enable for Base Image

Click on Save:

We succeed to link our GitHub repository to the Docker repository. If you need help with Docker builds, this link is helpful.

What's next? First, we'll install Docker. Then we'll make some changes to the code and Travis CI.

To install Docker, go to Docker's Get Started page, select Docker for Developers and click on Download Desktop and Take a Tutorial:

To make sure you've installed Docker and verify it's running properly, open your command line and write "docker." Then validate:

Now, go back to your IDE or text editor; we'll make some changes to the code.

Create a file named "Dockerfile." To sum up what we've done so far, the Dockerile is useful when creating Docker images. To better understand the purpose of this file, this Dockerfile reference will help you.

To keep things simple, I use this Callicoder Dockerfile example and make little changes. This is what the Dockerfile looks like:

Here's the Dockerfile creating a process using STS 4:

Select the project, then click on New -> File

Fill the file name field with "Dockerfile" and click the Finish button:

Copy and paste the content of Dockerfile presented previously:

Before making some changes to the pom.xml, let's look at the actual content:

We add Spotify's dockerfile-maven-plugin to push the project on Docker Hub:

"... to ensure the jar is unpacked before the Docker image is created, we add some configuration for the dependency plugin."

To continue, we will link Travis CI to Docker from our GitHub repository.

Do you remember your Docker username and password? Well, you will have to do so in order to proceed. We will create two environment variables in Travis CI.

To get there, just copy and paste this ( in your browser. But replace GITHUBUSERNAME with your correct username or click on your Travis CI badge present in

Click on More options -> Settings :

Fill in the form as follows:


Value: yourdockerpassword

Click Add button


Value: yourdockerusername

Click Add button

To deploy on Docker, we'll use "mvn deploy" as explained by Spotify. The Apache Maven Project explains the role of the Apache Maven Deploy Plugin as a plugin used to "add artifacts to a remote repository."

But we don't want to add artifacts to a remote repository, we just want to deploy it on Docker. So, when we call the deploy phase, we must include a valid section POM. However, that's not the purpose here. Thus, we'll add this property in pom.xml:


If we don't add this property, this error will occur:

"**[ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy (default-deploy) on project cicd-applied-to-spring-boot-java-app: Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter -> [Help 1]**"

At this stage, it's time to use those two Docker environment variables. Just copy and paste this new .travis.yml and push it on GitHub:

Commit description: "Linking Travis CI to Docker"

We received a beautiful red cross and Travis CI badge, meaning a beautiful error! But ignore that for now, we'll correct it later!

Ladies and gentlemen, I'm happy to present to you: our beautiful error! Just go to the Travis CI repository and check out the beautiful build log:

The command "mvn deploy" exited with 1.

We've already added the Travis CI badge. Now, it's time to do the same for Docker. Go to

On the search bar, write "docker." Then, we'll get the following results:

Click on Docker Cloud Build Status:

What if I told you we'll get an error here also?

Nevermind, just fill the following form:

Click on the Copy Badge URL.

Now, go back to the GitHub repository and edit We'll add the following Docker badge:

Commit description: "Adding Docker badge"

Ladies and gentlemen, we are all winners here. So let's get it right!

Previously, we made changes on the pom.xml and created a Dockerfile.

All of those errors occurred due to the fact that Maven didn't know how to handle the deployment on Docker and the Dockerfile was absent so it was impossible to push images.

The time has come to push those changes (Dockefile and pom.xml) on GitHub using GitHub Desktop:

Ladies and gentlemen, who are we now? Winners!

Now, we have two ugly green badges meaning success! Just kidding! That's beautiful.

To be sure, check your emails. You should have received two emails: one from Travis CI and the other from Docker.

Before moving on to step three, we'll run the app without using Docker only. Just remember to replace "fanjups" with your own Docker Hub username:

I got the following error: "Invalid or corrupt jarfile /app.jar." It's all about encoding, so I'll add those two properties to the pom.xml.

Now, it's time to commit on GitHub. If you're confused about writing useful commit messages,

Before running the app again, it's important to list all containers using docker ps.

Then check the "CONTAINER ID," stop (docker stop "CONTAINER ID"), and remove it (docker rm "CONTAINER ID") because it's persisted, as explained by this post on Spring Boot with Docker.

Then, we'll run again the app to ensure that everything works well:

I was so happy when I solved this problem!

The core steps are now over. We've successfully implemented the CI/CD. Now, let's add some useful tools!

Step 4: Add Codecov for Code Coverage

First, make sure you've updated the project on your computer:

Click on Pull Origin:

Copy the modified files which we'll use in IDE from our GitHub folder and then paste them into our workspace. In this case, we'll only copy and paste the pom.xml.

Don't forget to refresh the project on STS 4 and do whatever it takes to include changes.

To better use this tool, we make some changes by adding a unit test.

First, create a new package — com.cicd.cicdappliedtospringbootjavaapp.controller.

Secondly, create a new class and change as follows:

The folder looks like:

Before running the app on your computer, you can skip the entire dockerfile plugin because the deployment will take place on the GitHub repository managed by Travis CI.

To do this, just add this option (-Ddockerfile.skip), as explained by Spotify dockerfile-maven-plugin's usage, to your Maven command. Finally, we get mvn spring-boot:run -Ddockerfile.skip.

Now, log in or sign up to Codecov with GitHub.

Click on Account -> Repositories -> Add new repository

Just choose your GitHub repository or follow this link But remember to replace GITHUB_REPOSITORY with cicd-applied-to-spring-boot-java-app and the GITHUB_USERNAME with yours:

Last time, we added two environment variables to Docker. Now, we added the Codecov environment variable: CODECOV_TOKEN, as well. Copy your token and add it to your Travis CI repository.

We made some changes to the pom.xml by adding the jacoco-maven-plugin.

Go back to GitHub repository and we'll edit .travis.yml.

What Time Is it? Codecov Badge Time!

Go to your Codecov repository and Click on **Settings -> Badge -> **Copy (from Markdown).

Then, go to your GitHub repository and paste it into

Finally, push your changes from your computer to GitHub.

Code Coverage: 60%

Perhaps, you want to deactivate the coverage and activate it later. If so, go ahead and create a file named codecov.yml. Now, it's useful to know coverage so I'll comment each line with "#."

If you wish to learn more, click here to read the docs.

Now, on to step 5!

Step 5: Use SonarCloud to Write Great Code

To start, log in or sign up with GitHub.

Click on + (Analyze new project or create new organization) -> **Analyze new project -> Import another organization -> Choose an organization on GitHub **

Next, make sure SonarCloud has access to your GitHub repository.

Now that we're back to SonarCloud, choose a Key. I suggest using "cicd-applied-to-spring-boot-java-app" as the Key.

Then, click on Continue -> Choose Free plan -> Create Organization -> Analyze new project -> Select your GitHub repository -> Set Up -> With Travis CI -> Provide and encrypt your token -> Copy

Go back to Travis CI and create a SonarCloud environment variable named SONAR_TOKEN. As a value, paste the token you've just copied.

Now, back to SonarCloud and click on Continue -> Edit your .travis.yml file -> Choose Maven as build technology -> Configure your platform -> Configure the scanner -> Copy.

I chose to write SonarCloud script under after_success instead of script because I focus on deployment here. You are free to place it where you want.

Also, create a file named and edit as follows: sonar.projectKey=GITHUBUSERNAME_cicd-applied-to-spring-boot-java-app

Go back to SonarCloud and click on Finish.

To end, we add a SonarCloud badge into

Here's the SonarCloud badge already added:

Now, on to step 6!

Step 6: Build a Project Site Using the GitHub site-maven-plugin

To get started, open pom.xml on your computer. We add:

**1) OAuth token and GitHub servers ** as properties

2) org.apache.maven.plugins:maven-site-plugin

3) com.github.github:site-maven-plugin

4) org.apache.maven.plugins:maven-project-info-reports-plugin

5) developers section

6) organization section

7) issueManagement section

8) Software Configuration Management (SCM) section

"The important configuration is to allow the OAuth token to be read from an environment variable (excerpt from pom.xml)" as explained by Michael Lanyon's blog. _"To create the token, follow these instructions". _

Copy the token, then create a new environment variable named GITHUB_OAUTH_TOKEN.

Push pom.xml to GitHub and edit .travis.yml by adding "- mvn site" under after_success.

After pushing all changes, gh-pages branch and project site are created. Each time you push, the site will be updated if necessary.

To see the site, click on environment -> View deployment (under Deployed to github-pages).

Here's a link to my GitHub repo.

Ok, great. Now, let's move on to step 7!

Step 7: Deploy the App on Heroku Using heroku-maven-plugin

Here we go! Log in or sign up for Heroku.

Click on New -> Create new app. To continue, enter an app name (cicd-spring-boot-java-app). cicd-applied-to-spring-boot-java-app is too long as an app name. Choose a region and click Create app.

Next, click Connect to GitHub.

Search the GitHub repository. Once you find it, click Connect.

Check** Wait for CI to pass before deploy.**

Click Enable Automatic Deploys.

Go to Account settings.

Copy your API KEY and create a new Travis CI environment variable named HEROKU_API_KEY. This the last environment variable linked to this project.

It's time to edit pom.xml and push to GitHub. We add:

1) full-artifact-name as a property

2) com.heroku.sdk:heroku-maven-plugin

Now, we focus on .travis.yml.

  1. To deploy on Docker Hub, we used mvn deploy.

  2. To deploy on Heroku, we'll use mvn heroku:deploy.

  3. In order to deploy on Docker and Heroku, we'll repeat the deploy phase twice, and risk exceeding timeout.

  4. To avoid that, we'll only use mvn heroku:deploy.

We succeeded in deploying on Heroku! Hooray! Now, go to

Now, it's time for the final step.

Step 8) Manage Topics

What does it mean to be in the last stage!? Topics are helpful when getting a quick overview of the project.

Go back to GitHub repository and click on Manage topics and add whatever you want.

By the way, we added a MIT license badge into the and license section of the pom.xml!


Congratulations! You're all done. To sum things up, you learned how to implement CI/CD on a Spring Boot Java app using Maven, GitHub, Travis CI, Docker, Codecov, SonarCloud, and Heroku. This is a template you are free to use.

If you're confused, please ask in the comments. I also suggest reading the docs available, as many times as necessary.

The code is available here. So just fork, it's all yours!

Get Jibby With Java, Docker, and Spring Boot

Get Jibby With Java, Docker, and Spring Boot

Get Jibby With Java, Docker, and Spring Boot Andrew Hughes. Docker is a very popular system for containerizing applications. Containerization packages the executable

Docker is a very popular system for containerizing applications. Containerization packages the executable code along with the runtime environment in deployable virtual images using a repeatable, automatable process.

In the world of cloud-based development and microservices, where a single application can be spread across hundreds of servers in various networks with complex port configurations, the ability to automate the deployment of “units” of code is super helpful. The ability to control the execution environment also offers advantages: managing variables like OS version, disk size, available memory, port configuration, etc… Containerization helps avoid unexpected conflicts when OS libraries create unexpected conflicts or bugs on update.

All of this control often comes at the cost of complexity, however. Creating and maintaining dockerfiles can be time-consuming. Jib to the rescue! Jib allows you to easily Dockerize Spring Boot projects, using plugins for Maven and Gradle. Beyond just ease of containerization, Jib also takes advantage of image layering and registry caching to speed up builds by only re-building the parts of an application that have changed.

In this tutorial, you will build a simple Spring Boot REST API and use Jib to dockerize it. You will use OAuth 2.0 and Okta to protect the resource server.

Let’s get started!

Install Dependencies

For this tutorial, you need to install a few dependencies. First, you’ll need Java. I’ve written the tutorial for Java 11, but it should be backward compatible with Java 8. If you don’t have Java installed, go to the AdoptOpenJDK website and install it. On a Mac, you can also use Homebrew.

The next tool you’ll need is HTTPie, a simple command-line HTTP client. Please follow instructions on their website to install it.

You’ll also need a free developer account with Okta. Okta is a SaaS (software-as-service) identity management provider. We make it easy to add features like single sign-on, social login, and OAuth 2.0 to your application. Sign up for an account on our website if you haven’t already.

Finally, you’ll need Docker Desktop. This allows you to quickly and easily run local Docker images on your computer. It’s great for testing, development, and tutorials like this. Check out the Docker Desktop website for installation instructions.

This tutorial uses Gradle as a build system, which you can install locally from their website, but it’s not required to install since the project starter will include a Gradle wrapper. But if you want to install Gradle locally, or just want to learn more about the project, check out the Gradle website.

You’ll also need some sort of code editor or IDE. I like Intellij IDEA Community Edition for Java development. It’s free and awesome. But there are tons of other options as well.

Use Spring Initializr to Download Initial Project

You installed HTTPie, right? In this section, you’re going to use it to command Spring Initializr to create and download your initial project.

From a command line:

http \ dependencies==web,okta \ groupId==com.okta.spring-docker.demo \ packageName==com.okta.spring-docker.demo \ type==gradle-project \ -d 

You can read about all of the parameters available on Spring Initializr’s REST API on the Spring Initializr GitHub page. The important points are that you specified a Gradle project, included a couple of dependencies, and specified your group and package information.

The two dependencies are web and okta. web is short for spring-boot-starter-web, which allows Spring Boot to serve HTTP requests. okta is short for Okta’s Spring Boot Starter, which simplifies adding Okta OAuth to Spring applications. If you’d like to learn more about this project, check out the Okta Spring Boot GitHub page.

The command above downloads a file named Unzip it somewhere and open it in the editor or IDE of your choice:

unzip -d spring-boot-docker 

This fully functioning Spring Boot app defines an empty Spring Boot application without any controllers, so it doesn’t do much. Before you fix that, you need to add one more dependency to the build.gradle file.

Just Jib it!

To add Jib to the Gradle project, simply add the plugin to the build.gradle file. If you want to dig in deeper, take a look at the Introducing Jib blog post or Jib’s GitHub page.

Add id '' version '1.3.0' to the plugins closure at the top of the build.gradle file, like so:

plugins { id 'org.springframework.boot' version '2.1.5.RELEASE' id 'java' id '' version '1.3.0' // <-- ADD ME } 

If you open a shell and navigate to the project root, you can now run ./gradlew tasks and see the tasks that the new plugin has added to the project.

Jib tasks --------- jib - Builds a container image to a registry. jibBuildTar - Builds a container image to a tarball. jibDockerBuild - Builds a container image to a Docker daemon. 

In this example, you will be using the jibDockerBuild tasks. This pushes the image to the Docker daemon run by Docker Desktop. This is great for local development and testing.

More often in a larger production environment, you would push to a container registry using jib. Jib can easily push to a variety of container registries, such as Google Container Registry, Amazon Elastic Container Registry, Docker Hub Registry, and Azure Container Registry.

Note that Docker Desktop has to be running in order for the jibDockerBuild task to work. Go ahead and start Docker Desktop if it isn’t already running.

Add a Web Controller and Configure Security

In order for your application to respond to HTTP requests, you need to add a controller. Add a new file called in the directory src/main/java/com/okta/springdocker/demo.

package com.okta.springdocker.demo; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; @RestController public class WebController { @RequestMapping("/") public String home() { return "Welcome!"; } } 

You also need to configure the security settings for this project. For the moment, you’ll want to allow all requests, so update your file to the following:

package com.okta.springdocker.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Configuration; import; import; @SpringBootApplication public class DemoApplication { public static void main(String[] args) {, args); } @Configuration static class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests().anyRequest().permitAll(); } } } 

Try it Out!

Build the project and push the Docker image to the local registry using the following command (from the project root dir):

./gradlew build jibDockerBuild 

After this completes, you should be able to list the Docker images:

docker images 

And see your application image in the local Docker registry:

REPOSITORY TAG IMAGE ID CREATED SIZE demo 0.0.1-SNAPSHOT 490d12302a6d 49 years ago 146MB 

To run your Spring Boot app, use the following command:

docker run --publish=8080:8080 demo:0.0.1-SNAPSHOT 

This command specifies the image repository and tag as well as instructing Docker to map port 8080 in the image to local port 8080.

Now you can use HTTPie to run a simple request:

http :8080 

And you should see:

HTTP/1.1 200 Cache-Control: no-cache, no-store, max-age=0, must-revalidate Content-Length: 8 Content-Type: text/plain;charset=UTF-8 ... Welcome! 

Sweet! So, at this point, you’ve created a simple Spring Boot application with a basic web controller and overridden the default security settings to allow all requests. You’ve also created a Docker image, pushed it to your local Docker registry, and run the image - all without a Docker file!

The next step is to add JSON Web Token (JWT) authentication using OAuth 2.0 and OpenID Connect (OIDC). The provider you’re going to use for this tutorial is Okta.

Create an OIDC Application

Create an OIDC application on Okta using your developer account. If you don’t have one, signup and return to this tutorial after activating your account.

Sign in to the Okta developer console. If this is your first time to log in, you may need to click the Admin button in the upper right-hand corner to get to the developer console.

Next, you will create an OpenID Connect (OIDC) application. OAuth 2.0 along with OpenID Connect is the protocol spec Okta implements to allow your application to handle authentication and authorization securely with the Okta servers.

Click on the Application top menu. Click the Add Application button.

Select application type Web.

Click Next.

Give the app a name. I named mine Spring Boot Docker. The OIDC Debugger website allows you to create access tokens you can use to access your app with HTTPie. You need to add a login redirect URI and allow implicit flow for this website to work.

Under Login redirect URIs, add a new URI: []( "").

Under Grant type allowed, check the box next to Implicit (Hybrid).

The rest of the default values will work.

Click Done.

Leave the page open and take note of the Client ID. You’ll need it in a moment.

You’ll also want to know the Issuer URI from Okta. If you go to API in the top menu and click on Authorization Servers, you’ll see the default auth server. By default, all your OIDC apps are added to this auth server. The Issuer URI will be something like this: []( "").

You won’t need to do anything with it since this tutorial uses the Okta Spring Boot Starter and default values. The audience value, api://default, can be customized for more complex or custom applications.

Configure Spring Boot App for OAuth

First, rename the src/main/resources/ file to application.yml. Then add in the following values (filling in your Client ID and Okta URL):

okta: oauth2: issuer: https://{yourOktaDomain}/oauth2/default client-id: {yourClientID} 

If you were not using the Okta Spring Boot Starter, this configuration would be a little more extensive, but because you’re using the starter, it sets many defaults for you and simplifies setup.

Next, update the security configuration to use OAuth 2.0 and JWT authentication. In the file, update the configure(HttpSecurity http) method in the OktaOAuth2WebSecurityConfigurerAdapter static class to match the following:

@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests().anyRequest().authenticated() .and() .oauth2ResourceServer().jwt(); } 

Finally, change your file to match the following:

package com.okta.springdocker.demo; import; import; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import; @RestController public class WebController { @RequestMapping("/") public String home(@AuthenticationPrincipal JwtAuthenticationToken jwtAuthenticationToken) { return "Welcome " + jwtAuthenticationToken.getName() + "!"; } @RequestMapping("/info") public String info(@AuthenticationPrincipal JwtAuthenticationToken jwtAuthenticationToken) { return jwtAuthenticationToken.toString(); } } 

You could have left the WebController the same. This doesn’t affect authentication. The changes demonstrate how to get a little information about the authenticated party from Spring Security.

Run the App Again, with OAuth 2.0!

Stop the previous process if it’s still running. You should be able to Control-C from the shell where you ran the docker run command. If that doesn’t work, you can use the following command to stop all running docker containers:

docker stop $(docker ps -a -q) 

From a terminal at the project root, run the following command to rebuild the project and the docker image:

./gradlew build jibDockerBuild 

Once this process completes, run the image:

docker run --publish=8080:8080 demo:0.0.1-SNAPSHOT 

Use HTTPie to make a request:

http :8080 

You’ll get:

HTTP/1.1 401 Cache-Control: no-cache, no-store, max-age=0, must-revalidate Content-Length: 0 ... 

Success! Of sorts. You still need to get a valid token. Fortunately, OpenID Connect debugger allows you to do that easily (remember when you added this URL to the list of authorized redirect URLs in your OIDC app on Okta?).

In a browser, go to

Update the following values:

  • Authorize URI: https://{yourOktaDomain}/oauth2/default/v1/authorize
  • Client ID: {yourClientID}
  • State: Any value really, I used This is the state

Scroll down and click Send Request.

Copy the token from the success screen and save it in a shell variable:


Now you can use the JWT in your request:

http :8080 "Authorization: Bearer $TOKEN" 

And see something like:

HTTP/1.1 200 Cache-Control: no-cache, no-store, max-age=0, must-revalidate Content-Length: 33 ... Welcome [email protected]! 

If you look back in the WebController class, you can see where we used dependency injection to get the JwtAuthenticationToken, which got the authenticated name:

"Welcome " + jwtAuthenticationToken.getName() + "!"; 

You can also try the /info endpoint (in the JwtAuthenticationToken class) for more detailed information.

Learn More about Docker and Spring Boot

In this tutorial, you learned how to use Jib to easily Dockerize Spring Boot applications. You also used Okta and OAuth 2.0 / OIDC to protect this application. You generated a JWT using the OIDC Debugger and tested the authentication using the command line.

You can find the source code for this example on GitHub.

Further reading:

Publish a Docker container from Bitbucket to Google Cloud Container Registry

Kubernetes Cluster Setup With Jelastic

How To Set Up Laravel App on Docker, With NGINX and MySQL

Developing WordPress Sites With Docker

Build Falcon API Framework on Docker