Important

In this article I am not going to setup a new node project, I am explaining how my example node docker container works. In this article we’ll use Release v1.0.0

This article will get into the logic of the files, and not on how docker works. Go to 41.01 Portainer containers to find out how to host this on docker.

This article assumes little knowledge about 20.08 node js, but it does assume that you know javascript and that you have 20.08 node js installed.

Things we are going to look int:

  • server.js
  • homepage/
    • index.html
    • script.js
    • style.css
  • package.json
  • settings.json

package-lock.json

Don’t touch package-lock.json, this is auto-generated by npm.

Node_modules

Don’t forget to add node_modules/ to your .gitignore

It should by default already be in the .gitignore

Introduction

Server.js

server.js is the home of our application. This gets run whenever we start the application, try to run the following command in your console:

npm run start

It should say something along the lines of: Server running at http://localhost:3001...

When you then go to http://localhost:3001, you will see a website. http://localhost:3001/test/isOnline and http://localhost:3001/test/visits are also reachable.

Let’s open the server.js file

When we open the server.js we’ll see a few things.

These are package imports, and the import of our settings.json

const cors = require("cors");
const path = require('path');
const express = require("express");
const expressStatic = require('express').static;
const settings = require("./settings");

expressStatic

In the above example, I am importing expressStatic seperately. You can also ignore the following line:

const expressStatic = require('express').static;

Then you have to replace the following line:

app.use(expressStatic(staticHtmlPath));

With the following line:

app.use(express.static(staticHtmlPath));

What we do here is import a cors, path and express package. Express is the package that handles our routing, and basically the whole api. Cors and path are packages that we use in combination with Express.

const port = settings.apiPort;

This loads our port that we use from the settings.json.

And this is what we have in our settings.json:

{
    "apiPort": 3001
}

The main api

The main api consists of the following lines:

const app = express();
app.use(cors());
// start the Express server
app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}...`);
}).on('error', (err) => {
    console.error('Server startup error:', err);
});

This is all we need for a basic api, but this is an empty api with nothing.

Info

You can add as many routes as you want to your Express api, just don’t make them overlap.

adding the homepage

The following lines are the only lines we need for a homepage.

const staticHtmlPath = path.join(__dirname, './homepage');
app.use(expressStatic(staticHtmlPath));

What it does is it loads every file in the homepage/ folder onto our api at the main path. Even subfolders

Change path

If you want to change it so that the files are not loaded onto the main url <main_url>/index.html but instead onto <main_url>/static/index.html, we change the following line:

app.use("static", expressStatic(staticHtmlPath));

The json pages

http://localhost:3001/test/isOnline and http://localhost:3001/test/visits are different from http://localhost:3001/index.html. These pages have logic.

This is because these pages are not static, and use the api approach:

var visit = 0;
 
const testRouter = express.Router();
testRouter.use(express.json());
 
testRouter.get("/isOnline", async (_req, res) => {
    visit++;
    console.log("Connection go brrr...")
    res.status(200).send({ "message": "The server is online." });
});
 
testRouter.get("/visits", async (_req, res) => {
    visit++;
    console.log("We have had " + visit + " visits since startup!")
    res.status(200).send({ "message": "We have had " + visit + " visits since startup!" });
});
app.use("/test", testRouter);

This is all the logic behind these 2 pages. I’ll break it down:

const testRouter = express.Router(); is so that we don’t have to manually tell Express that they are all on the /test/ url. This is a way to group them.

app.use("/test", testRouter); assigns the routes we defined to the API.

And the rest is quite easy:

testRouter.get("/routing_to_use", async (_req, res) => {
    // add logic here, this is just a function that get's executed whenever someone goes to this route.
    res.status(200).send({ "message": "We have had " + visit + " visits since startup!" }); // this is to send a response to the user that requests it.
});

you can also do testRouter.post etc. this is just the HTTP protocol it accepts.

package.json

{
    "dependencies": {
        "cors": "^2.8.5",
        "dotenv": "^16.4.5",
        "express": "^4.19.2"
    },
    "scripts": {
        "start": "node server.js",
        "dev": "nodemon server.js"
    },
    "devDependencies": {
        "nodemon": "^3.1.3"
    }
}

This is where we define our packages and commands. npm handles the packages automatically whenever we run something like npm install mongoose.

Thew reason why npm run start launches server.js is because we have set it to here: "start": "node server.js",. Yes, you can also start your api manually by running node server.js in your console.

Homepage folder

You can just put any static files here, like you’d put your website on 23.08 github pages. I’d advice to keep an file named index.html in every folder.

Default contents

The index.html, style.css and script.js that are on default in there are just my default page combi. You can just delete these. Or keep them if you like them, who am I to judge.