Skip to main content
Version: Torizon OS 6.x.y

Node.js on Torizon

Introduction

This article explains how to add Node.js to a Torizon Container and run an example application. This article also explains how to use Dockcer Compose to add the image to a device with an over-the-air update. For a more in-depth guide to application development with Torizon, please see the Torizon Documentation.

This article complies to the Typographic Conventions for Torizon Documentation.

For information about Node.js and Node RED on Toradex BSP, please see the Node.js and Node-RED on Linux article. For instructions on Node RED on Torizon, plese see the Node-RED article.

Sample

This article is build around a sample, available on the Torizon Samples Github. The pre-built image available on DockerHub.

Containers

Torizon OS applications run in containers, as containerized applications have advantages such as:

  • A container ships all the required files/libraries to run the program in a pre-built image, simplifying the deploy process, and reducing the chances of something breaking.
  • Updating a container does not leave residual files that can interfere with the program, or leave the program in a broken state by missing some file while downloading an update.

If you want to learn more about why we use containers in Torizon OS, see Torizon OS Technical Overview.

Dockerfile

The Dockerfile controls the Image build process. The Dockerfile defines the the base image (debian, ubuntu, etc.), the commands to run while creating the image, which files to copy to the image, and the commands to run when starting the image.

Prerequisites

How To

Create a Dockerfile

Create a text file named Dockerfile in an empty directory (<project-folder>). Be careful to not use any extension, the file name should be Dockerfile, not Dockerfile.txt.

Import the base Image

Open the Dockerfile and add the command below to import the base image, which contains the operating system and some libraries. In this example we will use the Torizon Debian image:

FROM --platform=linux/arm64/v8 torizon/debian:3-bookworm

The flag --platform=… tells docker that the image should be built for the board (arm), and not the development computer (x86).

Torizon Image

The Torizon Debian Image is a good starting point, having pre-configured hardware access, not running as root by default, and being tested on Torizon OS. For more information about the Torizon Debian Image, see Debian Containers for Torizon.

You may also use the Node Official Image, which is more frequently updated but lacks some of the Torizon Debian Image features.

Set the working directory

Lets set the working directory where the commands such as ADD, COPY, RUN, CMD, and ENTRYPOINT are executed. This way the files we copy ant the commands we run will output to our folder and not create a mess.

Add this command to your Dockerfile to set the working directory to /home/torizon:

WORKDIR /home/torizon

Install Node and NPM

We also need to install node and npm, as they don't come pre installed in the base image.

RUN apt-get update \
&& apt-get install -y --no-install-recommends nodejs npm \
&& apt-get clean \
&& apt-get autoremove \
&& rm -rf /var/lib/apt/lists/*

The --no-install-recommends prevents the installation of unnecessary packages, keeping the image smaller and with less packages to break. The last command, rm -rf /var/lib/apt/lists/*, clears the apt cache, reducing the image size.

Configure NPM

Lets configure npm, installed in the last section.

Lets set the NPM Log Level by setting the NPM_CONFIG_LOGLEVEL environment variable:

ENV NPM_CONFIG_LOGLEVEL info
tip

An ENV variable is saved to the image, providing a way to control the behaviour of applications on the deployed image. To set a variable for the container build step only, use ARG instead.

Install NPM Packages

For this basic web server example we are going to install express.

Add to your Dockerfile:

RUN npm install express

Expose ports

Lets declare our intent of using the port 3000 in our application:

EXPOSE 3000

The EXPOSE command makes the port accessible to other containers, but not to the host. It is good pratctice to include the EXPOSE, as it helps others understand what port the application listens by just reading the Dockerfile. For more information see the EXPOSE command documentation.

Copy files

We still need the app files in our image.

Lets copy the APP files from the computer to the image using the COPY command:

COPY app.js .

In this example we are going to move a single file, app.js, to the working directory ..

Set the application entrypoint

Lets configure the image to run node when starting.

ENTRYPOINT ["node"]
CMD ["app.js"]

Setting the entrypoint and cmd is equivalent to running the following command on a terminal inside the container:

## node app.js

Complete Dockerfile

The resulting Dockerfile from the commands above, with hard-coded variables replaced:

Create the JS appplcation

Create a file named "app.js" on the same folder of your Dockerfile and paste the following code:

The program starts a "hello-world" web server, listening on port 3000. The web page shows the device temperature (does not auto refresh).

Build the image

To build the image, on terminal with arm emulation enabled, cd to the Dockerfile folder and use the build command:

$ docker buildx build -t nodeapp .

The -t flag specifies a tag (name) for the image, in this case nodeapp.

info

If the docker daemon is not running, running a docker command will result in the following error:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

To start the docker daemon, use sudo systemctl start docker and to enable the docker daemon to start when the computer boots, use sudo systemctl enable docker.

To check if the docker daemon is running, use sudo systemctl status docker.

info

If the docker daemon is running but the user is not on docker group, running a docker command will result in the following error:
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock:

Please follow the instructions to run docker as a non-root user.

Run the program

Upload Image

Upload the container image to your docker hub account, to be later downloaded on the target device when updating:

$ docker login
$ docker tag nodeapp <dockerhub-account-name>/nodeapp:0.1.0
$ docker push <dockerhub-account-name>/nodeapp:0.1.0

The :0.1.0 specifies the image version, 0.1.0 in this case. It is recommended to increase the version number at every update, as images are only refreshed when the version number changes, or by explicitly requesting using command such as docker pull.

Configure Docker Compose

Lets use docker compose to configure the deployment of the container.

Create a file named docker-compose.yml and copy the following code to the file, replacing <dockerhub-account-name> with your DockerHub account name:

docker-compose.yml
services:
helloworld:
image: <dockerhub-account-name>/nodeapp
# A pre built image is also available:
# image: torizonextras/sample-nodejs
ports:
- "3000:3000"

image specifies where to get the image, if the image is not found locally.

ports specifies which host ports to attach to the container ports.

Update your device

Create a package on the Torizon Cloud Web UI using the Docker Compose file, then update the target device with the new package.

Test the App

After your device has been updated, open the web browser on your computer, enter the target device ip followed by the port 3000:

<target-device-ip>:3000
tip

Use the target device's hostname with a .local suffix (<hostname>.local) to access the device, insted of the device's IP.
For more information, see Using the Hostname.



Send Feedback!