DEV Community

rohitreddyk33
rohitreddyk33

Posted on

Deploying a MERN application over Kubernetes

Deploying a MERN(mongo-db, express, react-js, node-js) application using kubernetes.
This is a simple authentication application where the users can Register and Login. The login details of the users are stored in mongo-db database.
We are using React-js for the front end.

https://github.com/rohitreddyk33/dock

Registration page using React-js. The requests are made through API calls.



import {React,useState} from 'react'

function Register() {
  const[name,setName]=useState('')
  const[email,setEmail]=useState('')
  const[password,setPassword]=useState('')



  async function registerUser(event){
    event.preventDefault()
  const response=await fetch('http://<your service name after creating a service yaml file>.default.svc.cluster.local:7070/api/register',{
      method:'POST',
      headers:{
        'Content-Type':'application/json',
      },
      body:JSON.stringify({
        name,email,password
      }),
    })
    const data=await response.json()
    console.log(data)


  }
  return (
   <div>
    <h1>register</h1>
    <form onSubmit={registerUser}>
      <input type ="text" value={name} onChange={(e)=>setName(e.target.value)} placeholder="name"/>
      <input type ="email" value={email} onChange={(e)=>setEmail(e.target.value)} placeholder="email"/>
      <input type ="password" value={password} onChange={(e)=>setPassword(e.target.value)} placeholder="password"/>
      <input type="submit" value="register"/>
    </form>
   </div>

  )
  }

export default Register;
Enter fullscreen mode Exit fullscreen mode

Login page : If the users are already registered then they'll be able to view a page after logging in. Duplicate E-mails can't be used.

import { React, useState } from 'react'
import { useNavigate } from 'react-router-dom'

function Login() {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

  const navigate=useNavigate()
  function loginUser(event) {
    event.preventDefault()
    fetch('http://<your service name after creating a service yaml file>.default.svc.cluster.local:7070/api/login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        email, password
      }),
    }).then(res =>{
      return res.json();
    }).then(res =>{
      if(res.status==='ok'){
        localStorage.setItem('user',JSON.stringify(res))
      }

      navigate('/home')
    }) 
  }
  return (
    <div>
      <h1>Login</h1>
      <form onSubmit={loginUser}>
        <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="email" />
        <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="password" />
        <input type="submit" value="login" />
      </form>
    </div>

  )
}

export default Login;
Enter fullscreen mode Exit fullscreen mode

A basic home page after logging in:

import React from 'react'

function Home() {
  return (
    <div>Welcome User</div>
  )
}

export default Home
Enter fullscreen mode Exit fullscreen mode

Creating a schema and collection in the mongo-db database with the help of express


const mongoose=require('mongoose')
const User=new mongoose.Schema(
    {
    name:{type:String,required:true},
    email:{type:String,required:true,unique:true},
    password:{type:String,required:true},
    quote:{type:String},

},
{collection:'userdata'}
)
const model=mongoose.model('userdata',User)
module.exports=model
Enter fullscreen mode Exit fullscreen mode

We are using Node-js for backend. It receives the requests from users and performs functions accordingly. It also authenticates users through jwt authentication where it generates Tokens for the users.

const express = require('express')
const app = express()
const cors = require('cors')
const User = require('./models/model')
const jwt = require('jsonwebtoken');
app.use(express.json())
app.use(cors())
const mongoose = require('mongoose')
mongoose.connect("<your connection string which can be found in mongodb atlas after creating a cluster>")
 mongoose.connection.on('error', err => {
     console.log(err);
  });


app.post('/api/register', async (req, res) => {
    console.log(req.body)
    try {
        await User.create({
            name: req.body.name,
            email: req.body.email,
            password: req.body.password
        })
        res.json({ status: 'ok' })

    } catch (err) {
        res.json({ status: 'error', error: 'duplicate email' })
    }

}
)

app.post('/api/login', async (req, res) => {
    const user = await User.findOne({
        email: req.body.email,
        password: req.body.password
    })
    console.log(user)
    if (user) {
        const token = jwt.sign({
            name: user.name,
            email: user.email

        },
            <Your secret key for tokenization>
        )
        console.log(token);
        const userToken={name:user.name,email:user.email,token}
        return res.json({"status":"ok",'user':userToken})
    }
    else {
        return res.json({ 'status': 'error', user: false })
    }
})


app.listen(7070, () => {
    console.log("port 7070")
})
Enter fullscreen mode Exit fullscreen mode

Creating deployment yaml files for back-end.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mern-node  
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mern-node
  template:
    metadata:
      labels:
        app: mern-node
    spec:
      containers:
      - name: mern-node
        image:(your repository in docker hub where you built and uploaded the Image of the back-end code)
        ports:
        - containerPort: 7070
Enter fullscreen mode Exit fullscreen mode

Creating deployment yaml files for front-end.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: mern-react
  name: mern-react
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mern-react
  template:
    metadata:
      labels:
        app: mern-react
    spec:
      containers:
      - image: (your repository in docker hub where you built and uploaded the Image of the front-end code)
        name: mern-react
        ports:
        - containerPort: 3000
Enter fullscreen mode Exit fullscreen mode

creating a service file for back-end deployment

apiVersion: v1
kind: Service
metadata:
  name: node-service
spec:
  selector:
    app: mern-node
  type: ClusterIP
  ports:
  - port: 7070
    targetPort: 7070
Enter fullscreen mode Exit fullscreen mode

creating a service file for front-end deployment

apiVersion: v1
kind: Service
metadata:
  name: node-service
spec:
  selector:
    app: mern-node
  type: ClusterIP
  ports:
  - port: 7070
    targetPort: 7070
Enter fullscreen mode Exit fullscreen mode

Access your application through the service port of the node-port
Steps:

  1. kubectl describe service mern-service
  2. Get the port number for the node-port
  3. localhost: "node-port port number"

Top comments (8)

Collapse
 
naucode profile image
Al - Naucode

Hey, that was a nice read, you got my follow, keep writing 😉

Collapse
 
rohitreddyk33 profile image
rohitreddyk33

sure

Collapse
 
ajay4uuak profile image
Ajay • Edited

Hi I have greatest confusion how to connect mongodb in mern stack in kubernetes that is only eating my head please answer this

Collapse
 
rohitreddyk33 profile image
rohitreddyk33

mongoose.connect("")
mongoose.connection.on('error', err => {
console.log(err);
});

you have to give a connection string after creating a cluster in mogodb atlas.
once you have this in your code( in the part where you are using express, mongoose to connect to the database) create an image for react and node js. upload the respective images in docker hub and mention that image (to create a container) in deployment yaml files

Collapse
 
ajay4uuak profile image
Ajay • Edited

How does frontend talks to backend can you explain through cluster ip how it is done

Collapse
 
rohitreddyk33 profile image
rohitreddyk33

bro, cluster IP is just a service type which is used to host the application. The front talks to back end through API requests. The deployment yaml files for front end and back-end codes create containers. These containers are nothing but your front-end and back-end codes.
clear?

Collapse
 
akshaykumar profile image
Akshay Kumar

Finally thank god....I find this article very useful. Now I have a clear idea of deploying MERN application using kubernetes.

Collapse
 
vsaikeerti profile image
Veerabatula Sai Keerti

I find this very helpful. Thank you so much😊