Skip to content

Hello, World!

We'll begin with a simple "Hello, World!" demonstration to get you started with Windsor. In this tutorial, you will use the core blueprint's static website demo to serve a simple static HTML page. You should have some flavor of npm or yarn installed.

It is assumed you have already been through the quick start. You have created a repository, and are able to access a local cluster. To verify this, run:

kubectl get nodes

You should see something like:

NAME             STATUS   ROLES           AGE   VERSION
controlplane-1   Ready    control-plane   1h    v1.31.4
worker-1         Ready    <none>          1h    v1.31.4

Build a containerized web service

Let's first begin by building the application service. This service will involve an express.js web service with livereload configured. Add the following files to your project (source).

Create Dockerfile:

FROM node:22-alpine

WORKDIR /usr/src/server
COPY package.json package-lock.json server.js ./
RUN npm install
EXPOSE 8080
CMD ["node", "server.js"]

Create server.js:

const express = require('express');
const livereload = require('livereload');
const connectLivereload = require('connect-livereload');
const path = require('path');

// Create a livereload server
const liveReloadServer = livereload.createServer();
liveReloadServer.watch('/usr/src/app');

// Create an express app
const app = express();

// Use connect-livereload middleware
app.use(connectLivereload());

// Serve static files from the '/usr/src/app' directory
app.use(express.static('/usr/src/app'));

// Start the server
const PORT = 8080;
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

Create package.json:

{
  "name": "demo-static",
  "version": "1.0.0",
  "description": "Demo project to run server.js using express and livereload",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "connect-livereload": "^0.6.1",
    "express": "^4.21.1",
    "livereload": "^0.9.3"
  },
  "author": "",
  "license": "ISC"
}

Create docker-compose.yaml:

services:
  demo:
    build:
      context: .
    image: ${REGISTRY_URL}/demo:latest

Build and push the image:

docker-compose build demo && \
docker-compose push demo

Configure the static website demo component

To enable the static website demo, add the following to contexts/local/blueprint.yaml:

kustomize:
...
- name: demo
  path: demo
  dependsOn:
  - ingress-base
  force: true
  components:
  - bookinfo
  - bookinfo/ingress
  - static
  - static/ingress
...

You should have added the lines static and static/ingress to the demo block. This will enable the static demo as well as configure its ingress. To deploy these to your local cluster, run:

windsor install

Validate your resources

Check the status of all resources in the demo-static namespace by running:

kubectl get all -n demo-static

You should see something like:

NAME                          READY   STATUS    RESTARTS   AGE
pod/website-5b8b697588-g8zrf  1/1     Running   0          10s

As well as a service and ingress:

kubectl get svc -n demo-static
kubectl get ingress -n demo-static

Create static content

Check your environment variables by running windsor env. You should see one with the name PV_DEMO_STATIC_CONTENT. This path points to a folder under .volumes, such as pvc-420ddd3a-e7fd-455a-a2a4-a3388638777c. This is where you should place your static content, or direct the output of your build command. Place this file at ${PV_DEMO_STATIC_CONTENT}/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World</title>
</head>
<body>
    <h1>Hello, World!</h1>
    <p>Welcome to the static website demo.</p>
</body>
</html>

Assuming everything is working as expected, you should be able to visit http://static.test:8080 and see your content appear.

Inspect the environment

Let's have a look at what's been created. Run the following:

kubectl describe deployment website -n demo-static

Pay attention to the image tag. It should read registry.test/demo:latest. This image was pulled from the local registry that you pushed your image to in a previous step.

Inspect the persistent volume by running:

kubectl get pvc -n demo-static

You should see a persistent volume claim with a name matching the folder under .volumes/. This volume is bind mounted to your host, such that it shares content with pods under development.