Deploy locally NodeJS and MongoDB application using kubernetes

Yash Sharma
7 min readMay 30, 2021

Kubernetes is an open source container orchestration engine for automating deployment, scaling, and management of containerized applications

What we’re going to do in this tutorial:
1. Create NodeJS and Express Application
2. Setup MongoDB
3. Dockerizing the application and run locally using docker-compose
4. Converting docker-compose to kubernetes and deploy locally

We’ll be using Minikube for our local deployment, you check their website for installation steps.
Along with minikube, install kubectl, kubectl allows you to run commands against Kubernetes clusters. You can use kubectl to deploy applications, inspect and manage cluster resources, and view logs

Let’s start with the first step by creating nodejs application first

mkdir nodejs-mongodb-kubernetes && npm init --yes && yarn add express && mongodb

Create src/index.js file and copy below content

src/index.js

Next copy db.js in src folder and copy following content

src/db.js

Create Dockerfile and copy following content

Dockerfile

Create docker-compose.yml and copy following content:

docker-compose.yml

so if all the files in place the directory structure will look as follows:

if you’ll see docker-compose file line 4, there is local docker image (local-nodejs-kubernetes), to create the docker image run following command in the root of the project. don’t forget to copy dot(.) in the last

docker build -t local-nodejs-kubernetes .

once docker build successful, it will create docker image in you machine, now let’s try to run this images using docker-compose, run following command

docker-compose up --build -d

it will run the image and mongdb and exit from shell, run following command to see the running images.

docker-compose ps

you will see your running images and ports, now let’s see the logs of our service, run following command, nodejs-kubernetes is the name of the service in docker-compose.yml file

docker-compose logs -f nodejs-kubernetes

you will see following output:

Attaching to nodejs-mongodb-kubernetes_nodejs-kubernetes_1
nodejs-kubernetes_1 |
nodejs-kubernetes_1 | 🚀 Server is running!
nodejs-kubernetes_1 | 🔉 Listening on port 80
nodejs-kubernetes_1 | 📭 Click here http://localhost:80
nodejs-kubernetes_1 |
nodejs-kubernetes_1 | DB connection successful!

so based on the above logs, DB connection is successful and server is running on port 80, 80 is the internal port and we exposed it and bind the port with 8099 in docker-compose file, you can see port forwarding in docker-compose ps output, it will shows you ports 0.0.0.0:8099->80/tcp,:::8099->80/tcp , now let’s try to open http://localhost:8099 , you should see success message on browser like following image:

Next step is to Converting docker-compose to kubernetes, for that we’ll be using tool called Kompose, check the installation steps it’s very easy, once you installed successfully just go your project directory where docker-compose.yml file and run the following command

kompose convert

if command runs successfully you will get following output:

Create a directory called deployments move all the files in deployments, before moving just ensure minikube is running, you run command minikube start , if already running just check the status minikube status it will show the status of your cluster. along with that check kubectl is installed and type kubectl and press enter it will show bunch of commands. now let’s deploy out stack using kubectl, run following commands:

kubectl apply -f deployments

it will create and deploy service and once you can check status using following commands:

kubectl get pods

but you will see it will show error for local image:

NAME                                        READY   STATUS         RESTARTS   AGE
nodejs-kubernetes-5788bdd4f7-k7b4n 0/1 ErrImagePull 0 9s
nodejs-kubernetes-mongodb-77c4b9944-nzn6w 1/1 Running 0 9s

and after some time it will also show ImagePullBackOff , reason is kubernetes not able to download the local images, there are two ways to fix
1. set the docker env eval $(minikube docker-env) in shell and after that again build the image and set the imagePullPolicy to Never.
2. upload the local image to docker hub and it will run

let’s try both ways
go to shell and run the following command

eval $(minikube docker-env)

Now let’s build the image again

docker build -t local-nodejs-kubernetes:1 .

once done open nodejs-kubernetes-deployment.yaml after line 32 image: local-nodejs-kubernetes add this line and change image name to local-nodejs-kubernetes:1 see below

image: local-nodejs-kubernetes:1
name: nodejs-kubernetes
imagePullPolicy: Never

save the file and delete the deployment using command

kubectl delete -f deployments

and apply again

kubectl apply -f deployments

now check the running pods:

kubectl get pods
kubectl get pods

so if so far everything is well both of services are running, let’s check the service logs:

kubectl logs -f nodejs-kubernetes-56b84df6ff-sqhjv
service logs

so our service is up and running, however after few seconds it show error because service is not able to connect to mongodb and pod status show service is crashlooping

and if you will see the logs kubectl logs -f nodejs-kubernetes-56b84df6ff-sqhjv

connection timed out means service is not able to connect to MongoDB, to fix this let’s check the type of the service MongoDB, run the following command

kubectl get services

as mentioned in docs , we need to expose the mongo port to using type NodePort open file nodejs-kubernetes-mongodb-service.yaml and after line 11 spec: press enter indent and copy this type: NodePort

spec:
type: NodePort

make sure to indent equal to ports and also change the port to 27017, NodePort will assign the external port automatically, save the file and apply the configuration again or delete and apply whole stack

kubectl apply -f deployments/nodejs-kubernetes-mongodb-service.yaml

and also delete the pod, first check the pods by running kubectl get pods and delete the service pod

once delete kubernetes will bring it back and if you check the status it will show running and check the logs as well, you should see following output

now if you will check the services using kubectl get services you should see like this

Next step is to expose the service so that we can access it though browser, open the file nodejs-kubernetes-service.yaml after line 11 press enter and copy another type: LoadBalancer

spec:
type: LoadBalancer

save the file and apply kubectl apply -f deployments/nodejs-kubernetes-service.yaml and delete the pod and now if you will check the services again

you will type LoadBalancer for node-kubernetes service and port is also assigned by kubernetes itself however if you will try to open in browser it will still not work because EXTERNAL-IPcoming as <pending> , so for local deployment purpose we need to minikube tunnel, open another shell and run command

minikube tunnel

once this is done check the kubectl get services and you will see external ip assigned

now try to open http://10.111.140.118:8099/ and you will see success message if everything goes well,

2 .upload the local image to docker hub and it will run — let’s try this now

create a new docker image and change the success message from success to hello kubernetes! go to index.js and on line 10 change like below and save the file

res.json('Hello kubernetes!')

now let’s build the image in new terminal with your username as in docker or you can tag later on whatever suitable

docker build -t yasharma6121991/local-nodejs-kubernetes:1 .

now push this image to docker hub and open the file nodejs-kubernetes-deployment.yaml and also comment line 34 # imagePullPolicy: Neverchange the image name save the file, apply the configuration again

kubectl apply -f deployments/nodejs-kubernetes-deployment.yaml

check the pod status it will show terminating old and creating new one

now refresh the page and you will see new message

Hurray! you are able to run deploy and run services using kubernetes, i know there are rooms for improvement and it’s not production setup one thing is missing that is MongoDB volume mounting because if MongoDB service re-deployed it will lost the data. once tested you can stop the minikube and delete the stack

kubectl delete -f deployments
minikube stop

Thanks for reading, let me know your comments and you can check the code in Github repo

--

--

Yash Sharma

Senior Full Stack developer (Nodejs, ReactJS, MongoDB, TypeScript, MSSQL, Docker))