Minikube is a tool that runs a single-node Kubernetes cluster in a virtual machine on your personal computer. We are going to deploy and run NodeJS rest API on MInikube in this article. First, we create an API and run it normally, then we will run the same on the Docker and, finally, we create a deployment and service objects to deploy and run it on Kubernetes locally.
We are going to need some pre-requisites to complete this project or run it on your local machine.
Since this post is all about how we can run NodeJS API on local Kubernetes we are not going to focus much on API itself.
Here is a simple NodeJS API with two routes / and /name:myname returnsHello World and returning whatever the name you entered respectively.
const http = require('http');
const qs = require("querystring");
const url = require('url');
const port = process.env.PORT || 3000
const server = http.createServer((req, res) => {
if (req.method !== 'GET') handleError(405, res);
const {pathname, query} = url.parse(req.url);
if (pathname === '/name') {
const {name} = qs.parse(query);
if (name) {
res.end(`<h1>You Entered: ${name.toUpperCase()}</h1>`)
} else {
res.end("Bad Request");
}
}
if (pathname === '/') {
res.end(`<h1>Hello World</h1>`)
}
});
function handleError(code, res) {
res.statusCode = code;
res.end(`{"error": "${http.STATUS_CODES[code]}"}`);
}
server.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
index.js
Here is the Github link. You can clone it and run it on your machine
// clone it
git clone https://github.com/bbachi/nodejs-restapi-minikube.git
// install and start the project
npm install
npm start
Docker is a container runtime that Kubernetes uses. You can use another container runtime but the Docker is most popular for now. Let’s run this Node API on Docker. We need to define Dockerfile first which is used to automate the Docker image creation. Docker builds images by reading instructions from the Dockerfile.
Here is the Dockerfile for this project. We are building the image from base image node:10 and copying the package.json to install all the dependencies. Copying just package.json to install all the dependencies is one of the best practices. Docker builds images from the layers in the cache. We don’t want to repeat installing if there is a change in the index.js.
# stage1 as builder
FROM node:10-alpine
WORKDIR /api
COPY . .
EXPOSE 3000
ENTRYPOINT ["node", "index.js"]
Dockerfile
Let’s build the image and run it on docker with these instructions.
// building the image
docker build -t node-api .
// list images
docker images
// Run the container
docker run -d --name nodeapi -p 3000:3000 node-api
Once you run the above commands you can hit these URLs in the browser. You can exec into a running container and see the file system inside the container.
// urls
http://localhost:3000/name?name=somename
http://localhost:3000/
// exec into the running container
docker exec -it nodeapi /bin/sh
A pod is a group of one or more containers that share the storage and network and has the specification on how to run the container. You can check the pod documentation here.
Running Local images on Minikube
Kubernetes always try to pull images from the Docker registry. If you want to use your local docker images you need to do certain steps on your local machine.
// set the environment
eval $(minikube docker-env)
// build the image
docker build -t node-api .
// list the images
docker images
Let’s create a pod with the below file. Before that, You need to start the Minikube on your local machine with this command minikube start
and create a pod with this kubectl create -f pod.yml
apiVersion: v1
kind: Pod
metadata:
name: node-api-pod
spec:
containers:
- image: node-api
name: node-api
imagePullPolicy: Never
resources: {}
ports:
- containerPort: 3000
pod.yml
You can exec into the file system with this command kubectl exec -it node-api-pod .bin/sh
exec into a running pod
Deployment
Creating just one pod is not enough and what if you want to scale out the application and want to run 10 replicas at the same time. What if you want to change the number of replicas depending on the demand. That’s where the deployment comes into the picture. We specify the desired state in the deployment object such as how many replicas you want to run etc.
Kubernetes makes sure that it always meets the desired state. It creates replica sets which inturn creates pods in the background. Let’s create a Deployment for our project with this command kubectl create -f deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nodeapi
name: nodeapi
spec:
replicas: 5
selector:
matchLabels:
app: nodeapi
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nodeapi
spec:
containers:
- image: node-api
name: node-api
imagePullPolicy: Never
resources: {}
ports:
- containerPort: 3000
status: {}
deployment.yml
We have 5 replicas in the specification and the deployment creates 5 pods and 1 replica set.
deployment
Service
Service is an abstract way to expose an application running on a set of Pods as a network service. Let’s create a service with type NodePort so that we can access the nodejs API from the browser. Here is the service object YAML
apiVersion: v1
kind: Service
metadata:
name: nodeapi
labels:
run: nodeapi
spec:
ports:
- port: 3000
protocol: TCP
selector:
app: nodeapi
type: NodePort
service.yml
Create a service with this command kubectl create -f service.yml
and you can list the service with this kubectl get svc
Running services
We have created deployment and services and now we need to access this deployment from the browser.
We need to get the public IP address of the Kubernetes with this command kubectl cluster-info
master is running at 192.168.64.2
Get the port from the service object that we just created with this command kubectl get svc
service is listening on port 32329
Let’s access the nodejs API with this IP address 192.168.64.2 and port 32329 with the below URLs. Make sure that you use Http instead of Https.
// endpoints port and IP address might change
http://192.168.64.2:32329/name?name=myname
http://192.168.64.2:32329/
Here is the result
Accessing API in the browser
It’s always convenient to use Minikube and own docker images for the local testing. We don’t even deploy in some kind of environment to test our workflow.
Thank you for reading!
#node-js #docker #kubernetes #rest-api #webdev