DEV Community

Cover image for Introduction to Docker and Kubernetes with Node.js
Paulo Messias
Paulo Messias

Posted on

Introduction to Docker and Kubernetes with Node.js

Hey devs!

With the growing adoption of microservices and the need for scalability, Docker and Kubernetes have become indispensable technologies. While Docker facilitates the creation and management of containers, Kubernetes orchestrates these containers in a cluster, providing high availability and scalability. Let's explore how to use Docker and Kubernetes to deploy a Node.js application.

Prerequisites

Project Structure

Let's create a simple Node.js project with the following folder structure:

my-node-app/
├── src/
   └── index.js
├── Dockerfile
├── .dockerignore
├── package.json
└── k8s/
    ├── deployment.yaml
    ├── service.yaml
    └── ingress.yaml
Enter fullscreen mode Exit fullscreen mode

Step 1: Setting Up the Node.js Application

First, let's create the Node.js application.

package.json File
Create the package.json file with the following content:

{
  "name": "my-node-app",
  "version": "1.0.0",
  "description": "A simple Node.js app",
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js"
  },
  "dependencies": {
    "express": "^4.17.1"
  }
}
Enter fullscreen mode Exit fullscreen mode

src/index.js File
Create the src directory and, inside it, the index.js file with the following content:

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(port, () => {
  console.log(`App running on http://localhost:${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Step 2: Dockerizing the Application

Dockerfile
Create a Dockerfile in the root of the project with the following content:

# Use the official Node.js base image
FROM node:14

# Create a working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Expose the application port
EXPOSE 3000

# Command to start the application
CMD ["npm", "start"]
Enter fullscreen mode Exit fullscreen mode

.dockerignore File
Create a .dockerignore file in the root of the project to prevent unnecessary files from being copied to the container:

node_modules
npm-debug.log
Enter fullscreen mode Exit fullscreen mode

Building and Running the Container
To build and run the container, execute the following commands:

docker build -t my-node-app .
docker run -p 3000:3000 my-node-app
Enter fullscreen mode Exit fullscreen mode

Step 3: Orchestrating with Kubernetes

Let's create the Kubernetes manifests to deploy the application in a cluster.

k8s/deployment.yaml File
Create the k8s directory and, inside it, the deployment.yaml file with the following content:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-node-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-node-app
  template:
    metadata:
      labels:
        app: my-node-app
    spec:
      containers:
      - name: my-node-app
        image: my-node-app:latest
        ports:
        - containerPort: 3000
Enter fullscreen mode Exit fullscreen mode

k8s/service.yaml File
Create the service.yaml file in the k8s directory with the following content:

apiVersion: v1
kind: Service
metadata:
  name: my-node-app-service
spec:
  selector:
    app: my-node-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer
Enter fullscreen mode Exit fullscreen mode

Deploying to Kubernetes
To deploy the application to Kubernetes, execute the following commands:

kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
Enter fullscreen mode Exit fullscreen mode

Check if the pods are running:

kubectl get pods
Enter fullscreen mode Exit fullscreen mode

And the service:

kubectl get services
Enter fullscreen mode Exit fullscreen mode

The service should display an external IP address where the application will be available.

Step 4: Setting Up Ingress in Kubernetes

To expose the application using an Ingress resource, we need to configure an Ingress controller and create an Ingress resource.

Enabling the Ingress Controller in Minikube
Enable the Ingress controller in Minikube with the following command:

minikube addons enable ingress
Enter fullscreen mode Exit fullscreen mode

k8s/ingress.yaml File
Create the ingress.yaml file in the k8s directory with the following content:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-node-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: my-node-app.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-node-app-service
            port:
              number: 80
Enter fullscreen mode Exit fullscreen mode

Deploying the Ingress Resource
Apply the Ingress resource to the cluster:

kubectl apply -f k8s/ingress.yaml
Enter fullscreen mode Exit fullscreen mode

Testing the Ingress
To test the Ingress, add an entry to your /etc/hosts file to map my-node-app.local to the Minikube IP. Get the Minikube IP with:

minikube ip
Enter fullscreen mode Exit fullscreen mode

Then, add the following line to your /etc/hosts file:

<minikube-ip> my-node-app.local
Enter fullscreen mode Exit fullscreen mode

Replace with the actual IP address returned by the minikube ip command.

Now, you should be able to access the application at http://my-node-app.local.

Conclusion

In this post, we created a simple Node.js application, dockerized it, deployed it to a Kubernetes cluster, and exposed it using an Ingress resource. Docker and Kubernetes are powerful tools that, when combined, provide an efficient way to manage and scale applications. With these tools, you can ensure that your applications are always available and easily scalable as needed.

Top comments (1)

Collapse
 
gianlucam76 profile image
Gianluca

Thanks for sharing this. The final image size with your Dockerfile is huge though (858MB).

Can you suggest a multi-stage docker file to reduce the size?

Thanks