October 20, 2020 - ai ai-ml

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

Xavier Geerinck

@XavierGeerinck

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