Skip to content

eins78/hello-world-web

Repository files navigation

Hello World (Wide) Web

Small toy web server with a few features to test and debug several HTTP- and web-related festures. Main purpose is to test CI/CD workflows (builds, deployments, …) and tools (Docker, Kubernetes, …) and services.

  • no build step
  • relatively small footprint (less than 2MB in prod)
  • larger dev-dependencies (typescript, eslint, prettier, >50MB), usefull to compare build sizes of dev vs prod
  • CSS styles as static assets, to check proper routing/serving.

Run, then open http://localhost:8080 or open http://localhost:$PORT.

Run with nodejs

npm ci --prod
npm start

Run with docker

Use a prebuilt image, or build one locally with Docker either directly or using buildpacks.

use a prebuilt image hosted on the Github Container registry

IMG=ghcr.io/eins78/hello-world-web:main
docker pull $IMG

build locally and run

IMG=hello-world-web
docker buildx build --build-arg BASEIMAGE=$NODE_BASEIMAGE --load -t $IMG .

build with buildpacks

Builds in a docker "builder" Docker container and outputs a "runner" Docker image.

brew install buildpacks/tap/pack

source VERSION.env
IMG="eins78/hello-world-web-buildpacks:${VERSION}.0"
PACK_BUILDER="paketobuildpacks/builder:base"

pack build "$IMG" --builder "$PACK_BUILDER"
# to publish: docker push "$IMG"

run the image

export PORT=8080
export "APP_TITLE=Hello ${USER}@$(hostname -s)"!
docker run --rm -it -e APP_TITLE -e PORT -p $PORT:$PORT $IMG

Run with docker-compose

export PORT=8080
cp .env-default .env
docker compose up --build

Run with systemd and Docker

install systemd config and service:

curl -fsSL https://raw.githubusercontent.com/eins78/hello-world-web/main/deploy/systemd/hello-world-web.conf | sudo tee /etc/hello-world-web.conf
curl -fsSL https://raw.githubusercontent.com/eins78/hello-world-web/main/deploy/systemd/hello-world-web-docker.service | sudo tee /etc/systemd/system/hello-world-web.service
sudo systemctl daemon-reload
sudo systemctl enable hello-world-web
sudo systemctl restart hello-world-web
sudo systemctl status hello-world-web
sudo journalctl -efu hello-world-web 

Run with systemd and node.js

Install node.js, see nodesource/distributions. Debian/Ubuntu example:

curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - && \
sudo apt-get install -y nodejs

install app code, config and systemd service:

sudo git clone https://github.com/eins78/hello-world-web.git /opt/hello-world-web
sudo cp /opt/hello-world-web/deploy/systemd/hello-world-web.conf /etc/hello-world-web.conf
sudo cp /opt/hello-world-web/deploy/systemd/hello-world-web.service /etc/systemd/system/hello-world-web.service
sudo mkdir -p /var/www/
sudo chown -R www-data /var/www /opt/hello-world-web /etc/hello-world-web.conf
sudo systemctl daemon-reload
sudo systemctl enable hello-world-web
sudo systemctl restart hello-world-web
sudo systemctl status hello-world-web
sudo journalctl -efu hello-world-web 

Debugging

default (HTTP) port

All examples assume that port 8080 will be configured, but this port is nowhere used as a default so any misconfiguration will be spotted. A different default port is used for every way that it can be configured, so its easy to see from the resolved value which configuration was applied. This table also shows the order of precendence (last wins, if applicable).

config port
webserver 9999
.envfile 4444
Dockerfile 7777
docker-compose.yaml 3333
PORT env var 8080

Healthcheck

There is a healthcheck script that checks if the homepage is served with a non-error status. Note that the query parameter ?healthcheck is used, but not handled specifically by the server, it just helps to identifiy the healthcheck requests in logs.

  • GET https://localhost:${PORT}/api/time?healthcheck

  • Node.js script: bin/healthcheck.mjs

  • with docker and docker-compose, see

    ctr=hello-world-web-webserver-1
    docker inspect $ctr | jq '.[0].State.Health'

Development

npm i
npm dev

direnv

See https://direnv.net/#basic-installation.

brew install direnv || apt install direnv
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc

direnv allow .

Typescript in Javascript files

See https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html.