Introduction to Docker and Kubernetes with Node.js
Tags: docker, kubernetes, node, javascript
Published: 2024-06-04 15:00:41

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

- Basic knowledge of Docker and Kubernetes
- [Node.js installed](https://nodejs.org/en)
- [Docker installed](https://www.docker.com/)
- [Minikube (or another Kubernetes environment) configured](https://minikube.sigs.k8s.io/docs/start/)

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

```css
my-node-app/
├── src/
│   └── index.js
├── Dockerfile
├── .dockerignore
├── package.json
└── k8s/
    ├── deployment.yaml
    ├── service.yaml
    └── ingress.yaml
```
##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:

```json
{
  "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"
  }
}
```

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

```javascript
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}`);
});
```

##Step 2: Dockerizing the Application

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

```Dockerfile
# 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"]
```


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

```bash
node_modules
npm-debug.log
```

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

```bash
docker build -t my-node-app .
docker run -p 3000:3000 my-node-app
```

##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:

```yaml
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
```


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

```yaml
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
```


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

```bash
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
```

Check if the pods are running:
```bash
kubectl get pods
```

And the service:
```bash
kubectl get services
```

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:

```bash
minikube addons enable ingress
```

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

```yaml
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
```

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

```bash
kubectl apply -f k8s/ingress.yaml
```

**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:

```bash
minikube ip
```

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

```lua
<minikube-ip> my-node-app.local
```

Replace _<minikube-ip>_ 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.