Creating a simple "Hello World" docker application with Express and NodeJS
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 containereval $(minikube docker-env)
and validate withdocker 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