Add Docker to Your Spring Boot Application
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.
Prerequisites:
-
Java 11+ - Install with SDKMAN or directly from AdoptOpenJDK
-
Docker - I recommend Docker Desktop
-
An Okta account - More on that below
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 https://start.spring.io/starter.zip bootVersion==2.4.4.RELEASE \
dependencies==web,okta \
groupId==com.okta.spring-docker.demo \
packageName==com.okta.spring-docker.demo \
--download
And then unzip the downloaded file.
unzip demo.zip -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/WebController.java
:
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 DemoApplication.java
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 org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Configuration
static class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll();
}
}
}
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
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.
Reach out to Dockerfile reference for an explanation of all commands you can use. |
For your Spring Boot app, you’ll use a simple Dockerfile
file:
FROM openjdk:11 (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 11. |
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. |
You can browse through a lot of community containers to use as a base at DockerHub. |
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:
-
Change your code
-
Build the app
./mvnw package
-
Build the container
docker build . -t okta:spring_boot_docker
-
Run the container
docker run --publish=8080:8080 okta:spring_boot_docker
-
Stop the container
-
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
Before you begin, you’ll need a free Okta developer account. Install the Okta CLI and run okta register
to sign up for a new account. If you already have an account, run okta login
.
Then, run okta apps create
. Select the default app name, or change it as you see fit.
Choose Web and press Enter.
Select Okta Spring Boot Starter.
Accept the default Redirect URI values provided for you. That is, a Login Redirect of http://localhost:8080/login/oauth2/code/okta
and a Logout Redirect of http://localhost:8080
.
What does the Okta CLI do?
The Okta CLI will create an OIDC Web App in your Okta Org. It will add the redirect URIs you specified and grant access to the Everyone group. You will see output like the following when it’s finished:
Okta application configuration has been written to:
/path/to/app/src/main/resources/application.properties
Open src/main/resources/application.properties
to see the issuer and credentials for your app.
okta.oauth2.issuer=https://dev-133337.okta.com/oauth2/default
okta.oauth2.client-id=0oab8eb55Kb9jdMIr5d6
okta.oauth2.client-secret=NEVER-SHOW-SECRETS
NOTE: You can also use the Okta Admin Console to create your app. See Create a Spring Boot App for more information.
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.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
Let’s give it a try!
First compile and build your container.
./mvnw package
Then build the container:
docker build . -t okta:spring_boot_docker
The Okta CLI added your Okta settings to src/main/resources/application.properties
. However, you might want to check this file into source control. Therefore, it’s a good idea to remove the okta.oauth2.*
properties from this file and use environment variables instead.
To pass Okta info to the container as environment variables, you can use 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> \
okta:spring_boot_docker
Now if you hit 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 all it takes to secure your application with OIDC/OAuth 2.0!
Learn More About Spring, Docker, and Security!
In this tutorial, you learned how to build a Docker container for your Spring Boot app by writing the Dockerfile manually. There’s also a Maven plugin that can prepare the container for you. It’s called Jib and we cover it in more detail at Get Jibby With Java, Docker, and Spring Boot. Finally, Spring Boot 2.3 added built-in support for building Docker containers. Learn more in How to Docker with Spring Boot.
Other than that, we have more resources for you to continue learning about Java, Docker, Deployment, and OAuth 2.0:
The source code for this post is available on GitHub.
If you have any questions about this post, please add a comment below. For more awesome content, follow @oktadev on Twitter, like us on Facebook, or subscribe to our YouTube channel.
Changelog:
- Apr 2, 2021: Updated to use Java 11 and Spring Boot 2.4.4. See example app changes on GitHub. Changes to this article can be viewed in okta-blog#674.
Okta Developer Blog Comment Policy
We welcome relevant and respectful comments. Off-topic comments may be removed.