Node.js on Torizon
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.
This article is build around a sample, available on the Torizon Samples Github. The pre-built image available on DockerHub.
TorizonCore 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 TorizonCore, see TorizonCore Technical Overview.
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.
- A device running TorizonCore.
- A configured environment for building Torizon Containers.
- Torizon Platform Services account for OTA updates and deployment.
- DockerHub account.
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
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:
--platform=… tells docker that the image should be built for the board (arm), and not the development computer (x86).
The Torizon Debian Image is a good starting point, having pre-configured hardware access, not running as root by default, and being tested on TorizonCore. 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
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
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/*
--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.
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
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
Install NPM Packages
For this basic web server example we are going to install express.
Add to your Dockerfile:
RUN npm install express
For larger projects, a
package.json is easier to mantain compared to adding the dependencies directly to the Dockerfile.
package.json file in the Dockerfile folder, then add to
COPY command to the Dockerfile, to copy the
package.json to the image:
COPY package.json .
npm install command to run npm using the configuration from
RUN npm install
Lets declare our intent of using the port 3000 in our application:
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.
We still need the app files in our image.
Lets copy the APP files from the computer to the image using the
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.
Setting the entrypoint and cmd is equivalent to running the following command on a terminal inside the container:
## node app.js
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
$ docker buildx build -t nodeapp .
-t flag specifies a tag (name) for the image, in this case
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.
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 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
: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
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:
# A pre built image is also available:
# image: torizonextras/sample-nodejs
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 Platform 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
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.