React + Spring Boot Deployment(The Kubernetes Way)

React + Spring Boot Deployment(The Kubernetes Way)

In this article, we’ll go through a possible way to deploy Your Spring Boot application with React Front-end, given that it is being deployed to a Kubernetes Cluster. We will take advantage of the Dns feature of kubernetes that helps us to communicate between services and pods.

Without Kubernetes, you could still combine your Spring Boot application with A React Front-end. This involves building a static build of your React application and putting it in the /classes/public folder. The the resulting jar file contains the React Application as the Front-end of the Spring boot application. The full process is describe in this article.

This article provides an option if you would like to use the Unsupported Features of the next.js static export.

Some important assumptions for this to work

  1. Your Spring Boot Back-end routes are prefixed with a specific prefix, For example: /api

  2. Your React Front-end routes would fill the remaining routes.

  3. This is a bit experimental and would probably work more for a personal project, rather than for a big project.

For our use case, we don’t need to update our pom.xml to add some build plugins.

So we’ll just need to deploy the Spring boot application separately and deploy the React js application separately.

Frontend Proxy

The proxy url for the backend application is http://name-of-backend-service

For a regular react.js application, adding "proxy": "http://name-of-backend-service , would be all that is needed, but for a next.js, you would need to update the next.config.js file and add a rewrite like so:

const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  async rewrites() {
    return {
      fallback: [
        {
          source: '/api/:path*',
          destination: `[http://name-of-backend-service/api/:path*`](http://demo-backend/api/:path*`)
        }
      ]
    }
  }
}

module.exports = nextConfig

Kubernetes Definition Files

Now the Interesting part:

The ingress definition file:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: #INGRESS_NAME#
  namespace: #NAMESPACE#
spec:
  rules:
    - host: example.com
      http:
        paths:
          - backend:
              service:
                name: name-of-frontend-service
                port:
                  number: 3000
            path: /
            pathType: Prefix

React Js Definition File

apiVersion: v1
    kind: Service
    metadata:
      name: name-of-frontend-service
      namespace: #NAMESPACE#
    spec:
      ports:
        - port: 3000
          targetPort: 3000
      selector:
        app: frontend
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
      namespace: #NAMESPACE#
    spec:
      selector:
        matchLabels:
          app: frontend
      replicas: 1
      template:
        metadata:
          labels:
            app: frontend
        spec:
          containers:
            - image: #IMAGE_FRONTEND#
              name: frontend
              imagePullPolicy: Always
              ports:
                - containerPort: 3000

Spring Boot Definition file:

apiVersion: v1
kind: Service
metadata:
  name: name-of-backend-service
spec:
  ports:
    - port: 80
      targetPort: 8080
  selector:
    app: backend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  selector:
    matchLabels:
      app: backend
  replicas: 1
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - image: #IMAGE_BACKEND#
          name: backend
          ports:
            - containerPort: 8080

Conclusion

With this, our application is now taking advantage of Kubernetes’ DNS for Services and Pods.

A git repo for the demo project can be found here.