Creating a simple "Hello World" docker application with Express and NodeJS

Xavier Geerinck

October 20, 2020 / ai ai-ml

For a lot of infrastructure related blog posts I would like to utilize a very basic application that spins up a web server and allows us to access it. Once we access it we simple see a welcome message but with a delay that we can configure!

Note: Why a delay? Since we want to be able to test slow loading infrastructure! (load tests, scale tests, …)

Or in other words, when I access: http://localhost:3000/?name=Xavier%20Geerinck&delay=10000

I get:

Welcome back, Xavier Geerinck

-- Page loaded in 10s

So let’s build this with Node.JS and Express

Creating our Application

Prerequisites

As always, we start off by creating a folder for our project and initializing the project. To initialize this, we can use:

npm init -y
npm i express --save

Building the app code

Now for the application code it’s quite straightforward, we utilize express to start a server and then add a basic route that takes an incoming GET request at the root route / and takes in query parameters [ "name", "timeout" ].

const express = require('express')
const app = express()
const port = parseInt(process.argv[2]) || 3000;

app.get('/', async (req, res) => {
  const hrstart = process.hrtime();
  console.log('Processing incoming request!');

  let { name, timeout } = req.query;
  name = name || "John Doe";
  
  if (timeout) {
    console.log(`- Need to wait ${timeout}ms`);
    await delay(timeout);
  }

  console.log(`- DONE`);

  const hrend = process.hrtime(hrstart);

  return res.send(`Welcome back, <strong>${name}</strong><br /><br />-- Page timeout: ${timeout}ms<br />-- Page loaded in: ${hrend[0]}s ${hrend[1] / 1000000}ms`);
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

const delay = async (timeout = 1000) => {
  return new Promise((resolve, reject) => setTimeout(resolve, timeout));
}

Packaging it as a container

Whereafter we quickly create a Docker container out of it with the following Dockerfile

Dockerfile

FROM node:latest

WORKDIR /usr/src/app

# Install deps
RUN apt-get update

# Create Certificate
RUN apt-get install ca-certificates

# Install Package.json dependendencies
COPY package.json .
RUN npm install

# Copy Source Code
ADD . /usr/src/app

CMD [ "npm", "run", "start" ]
EXPOSE 3000

That we can then build with:

Note: Since we often want to develop locally, we don’t have to push the container. For that first load your minikube and then start building your container eval $(minikube docker-env) and validate with docker images

docker build -t local/myapp-helloworld .

Running it on Kubernetes

Once it is build, we can now run it on our Kubernetes cluster. For that we create a Deployment YAML file:

kubernetes.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: d-myapp-helloworld
spec:
  selector:
    matchLabels:
      app: myapp-helloworld
  replicas: 1
  template:
    metadata:
      labels:
        app: myapp-helloworld
    spec:
      containers:
      - name: container-myapp-helloworld
        image: local/myapp-helloworld:latest
        imagePullPolicy: Never # we compiled it locally
        ports:
        - containerPort: 8000

That we can apply with kubectl apply -f kubernetes.yaml and should now show the following after running kubectl get pods -A:

NAME                                  READY   STATUS    RESTARTS   AGE
d-myapp-helloworld-795f6f46b9-fh4pz   1/1     Running   0          2s

Xavier Geerinck © 2020

Twitter - LinkedIn