2 minute read

Minikube is a lightweight Kubernetes approach to run a simple cluster with only one node to test our applications. Minikube is available for Linux, macOS, and Windows systems.

Install required tools.

brew install minikube
minikube start

πŸ˜„  minikube v1.29.0 on Darwin 13.2.1 (arm64)
✨  Automatically selected the docker driver
πŸ“Œ  Using Docker Desktop driver with root privileges
πŸ‘  Starting control plane node minikube in cluster minikube
🚜  Pulling base image ...
πŸ’Ύ  Downloading Kubernetes v1.26.1 preload ...
    > preloaded-images-k8s-v18-v1...:  330.51 MiB / 330.51 MiB  100.00% 24.18 M
    > gcr.io/k8s-minikube/kicbase...:  368.75 MiB / 368.75 MiB  100.00% 10.16 M
πŸ”₯  Creating docker container (CPUs=2, Memory=6100MB) ...
🐳  Preparing Kubernetes v1.26.1 on Docker 20.10.23 ...
    β–ͺ Generating certificates and keys ...
    β–ͺ Booting up control plane ...
    β–ͺ Configuring RBAC rules ...
πŸ”—  Configuring bridge CNI (Container Networking Interface) ...
    β–ͺ Using image gcr.io/k8s-minikube/storage-provisioner:v5
πŸ”Ž  Verifying Kubernetes components...
🌟  Enabled addons: storage-provisioner, default-storageclass
πŸ„  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
brew install kubectl
kubectl cluster-info dump

Create a dummy Node.js Express application

Create a project and install packages

mkdir nodejs-docker-kubernetes
code nodejs-docker-kubernetes

npm init -y
Wrote to ../nodejs-docker-kubernetes/package.json:

  "name": "nodejs-docker-kubernetes",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  "keywords": [],
  "author": "",
  "license": "ISC"

yarn add express

Set up TypeScript for the project

yarn add -D typescript ts-node @types/node @types/express
// tsconfig.json
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "outDir": "dist",
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  "include": ["src"],
  "exclude": ["node_modules"]

Create app.ts for the application and add run scripts to package.json

import express, { Request, Response } from 'express';

const app = express();
const PORT = process.env.PORT || 3000;

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

app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
"scripts": {
  "start": "ts-node src/app.ts",
  "build": "tsc"

And run the service: yarn start

Build the Docker image and test-run it

Create a Dockerfile for the Node.js application:

FROM node:18

ENV NODE_ENV development

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .


CMD [ "node", "app.js" ]

Build the docker image and run a Docker container using the image. It should show β€œHello World!” in the GET request: http://localhost:8080/

docker build -t nodejs-docker-k8s .
docker run -d -p 8080:3000 --name nodejs-docker-k8s nodejs-docker-k8s

Deploy the image to Kubernetes cluster

Push the docker image to a container registry

docker login
docker tag nodejs-docker-k8s username/nodejs-docker-k8s
docker push username/nodejs-docker-k8s

Create Kubernetes deployment and service files

// deployment.yml
apiVersion: apps/v1
kind: Deployment
  name: nodejs-docker-k8s
  replicas: 1
      app: nodejs-docker-k8s
        app: nodejs-docker-k8s
      - name: nodejs-docker-k8s
        image: nodejs-docker-k8s
        - containerPort: 3000
// service.yml
apiVersion: v1
kind: Service
  name: nodejs-docker-k8s
    app: nodejs-docker-k8s
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer

Start Kubernetes cluster and apply the Kubernetes deployment and service

minikube start
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml