K8S + MiniKube+ Docker +Spring Boot REST API example
Table of contents
Introduction:
Containerization has revolutionized software development and deployment by providing a consistent and scalable environment for running applications. In this article, we will explore how to develop a Spring Boot application, containerize it using Docker, and deploy it on a local Minikube cluster. Minikube is a lightweight Kubernetes implementation that allows you to set up a local Kubernetes environment for testing and development purposes. Let's dive in and learn how to get started!
Prerequisites:
Before we begin, make sure you have the following prerequisites installed on your development machine:
Java Development Kit (JDK) 13 or higher
Docker
Minikube
kubectl (Kubernetes command-line tool)
Setup Application:
Step 1:
Set up the Spring Boot Application
To begin, let's create a simple Spring Boot application. You can either use an existing application or create a new one using Spring Initializr. Make sure your application runs successfully by executing it locally.
Create a new Spring Boot project or use an existing one.
Create a new Java class named
UserController
that will handle the REST API endpoints. Add the following code:
Create a User
class to represent the user entity. Add the following code:
public class User {
private Long id;
private String name;
private String email;
// Getters and setters
// Constructors
}
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/")
public ResponseEntity<List<User>> getUsers() {
List<User> users = userService.getAllUsers();
return ResponseEntity.ok(users);
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable("id") Long id) {
User user = userService.getUserById(id);
if (user != null) {
return ResponseEntity.ok(user);
} else {
return ResponseEntity.notFound().build();
}
}
@PostMapping("/")
public ResponseEntity<User> createUser(@RequestBody User user) {
User createdUser = userService.createUser(user);
return ResponseEntity.ok(createdUser);
}
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable("id") Long id, @RequestBody User user) {
User updatedUser = userService.updateUser(id, user);
if (updatedUser != null) {
return ResponseEntity.ok(updatedUser);
} else {
return ResponseEntity.notFound().build();
}
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable("id") Long id) {
boolean deleted = userService.deleteUser(id);
if (deleted) {
return ResponseEntity.noContent().build();
} else {
return ResponseEntity.notFound().build();
}
}
}
In this example, the UserController
class injects an instance of UserService
via constructor injection. The service layer is responsible for processing business logic and interacting with the repository DAO.
Create a new Java interface named UserService
defines the service layer methods. Add the following code:
public interface UserService {
List<User> getAllUsers();
User getUserById(Long id);
User createUser(User user);
User updateUser(Long id, User user);
boolean deleteUser(Long id);
}
The UserService
interface declares the methods for retrieving all users, retrieving a user by ID, creating a new user, updating a user by ID, and deleting a user by ID.
Create a new Java class named UserServiceImpl
implements the UserService
interface. Add the following code:
@Service
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public List<User> getAllUsers() {
return userRepository.findAll();
}
@Override
public User getUserById(Long id) {
Optional<User> userOptional = userRepository.findById(id);
return userOptional.orElse(null);
}
@Override
public User createUser(User user) {
return userRepository.save(user);
}
@Override
public User updateUser(Long id, User user) {
Optional<User> userOptional = userRepository.findById(id);
if (userOptional.isPresent()) {
User existingUser = userOptional.get();
existingUser.setName(user.getName());
existingUser.setEmail(user.getEmail());
return userRepository.save(existingUser);
} else {
return null;
}
}
@Override
public boolean deleteUser(Long id) {
Optional<User> userOptional = userRepository.findById(id);
if (userOptional.isPresent()) {
userRepository.delete(userOptional.get());
return true;
} else {
return false;
}
}
}
The UserServiceImpl
class implements the UserService
methods by interacting with the UserRepository
DAO.
Create a new Java interface named UserRepository
that extends JpaRepository<User, Long>
. Add the following code:
public interface UserRepository extends JpaRepository<User, Long> {
}
The UserRepository
interface extends the JpaRepository
the interface provided by Spring Data JPA, which provides generic CRUD operations for the User
entity.
Run the Spring Boot application, and the REST API endpoints will be available at the following URLs:
The service layer (UserServiceImpl
) will handle the business logic and interact with the repository DAO (UserRepository
) to perform CRUD operations on users.
Step 2:
Containerize the Spring Boot Application To containerize our Spring Boot application, we will create a Dockerfile. Create a file named Dockerfile
in the root directory of your project and add the following content:
FROM adoptopenjdk:13-jre-hotspot
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
This Dockerfile uses an OpenJDK 11 base image, sets the working directory to /app
, copies the Spring Boot application's JAR file into the container, exposes port 8080, and defines the command to run the application.
Step 3:
Build and Push the Docker Image Next, open a terminal and navigate to the root directory of your Spring Boot project. Build the Docker image by running the following command:
docker build -t my-spring-app .
Once the image is built successfully, you can optionally push it to a container registry such as Docker Hub for easier access in your Minikube cluster.
Step 4:
Set up and Start Minikube Ensure that Minikube is installed on your machine. Start Minikube by running the following command:
minikube start
This will create and start a local Kubernetes cluster using the Minikube driver.
Step 5:
Deploy the Spring Boot Application Now it's time to deploy our Spring Boot application to the Minikube cluster. We'll create a Kubernetes deployment and a service to expose the application.
First, create a file named deployment.yaml
and add the following content:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-spring-app-deployment
spec:
replicas: 1
selector:
matchLabels:
app: my-spring-app
template:
metadata:
labels:
app: my-spring-app
spec:
containers:
- name: my-spring-app-container
image: my-spring-app
ports:
- containerPort: 8080
This YAML file defines a deployment with a single replica, a selector, and a pod template that runs our containerized Spring Boot application.
Next, create a file named service.yaml
and add the following content:
apiVersion: v1
kind: Service
metadata:
name: my-spring-app-service
spec:
selector:
app: my-spring-app
ports:
- protocol: TCP
port: 8080
targetPort: 8080
type: NodePort
This YAML file defines a service that exposes our application on a NodePort, allowing us to access it from our local machine.
Apply both YAML files to the Minikube cluster by running the following commands:
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
Step 6:
Access the Spring Boot Application To access the deployed Spring Boot application, find the NodePort assigned to the service. Run the following command:
minikube service my-spring-app-service --url
This will provide you with a URL that you can use to access your application from a web browser or via cURL.
Conclusion:
In this article, we walked through the process of developing a Spring Boot application, containerizing it using Docker, and deploying it on a local Minikube cluster. Containerization provides a reliable and scalable environment for running applications, while Minikube offers a convenient way to test and develop Kubernetes deployments locally. By following these steps, you can start building and deploying your own containerized Spring Boot applications using Minikube and Kubernetes.
I hope this helps, you!!
More such articles:
https://www.youtube.com/@maheshwarligade
\==========================**=========================
If this article adds any value to you then please clap and comment.
Let’s connect on Stackoverflow, LinkedIn, & Twitter.