Bundle a Node.js app into a ROCK¶
This tutorial describes the steps needed to bundle a typical Node.js application into a ROCK.
Prerequisites¶
snap enabled system (https://snapcraft.io/docs/installing-snapd)
LXD installed (https://documentation.ubuntu.com/lxd/en/latest/installing/)
Docker installed (https://snapcraft.io/docker)
a text editor
Install Rockcraft¶
Install Rockcraft on your host:
sudo snap install rockcraft --classic --edge
Project Setup¶
Starting in an empty folder, create a src/
subdirectory. Inside it, add two
files:
The first one is the package.json
listing of dependencies, with the
following contents:
{
"name": "node_web_app",
"version": "1.0.0",
"description": "Node.js on a ROCK",
"author": "First Last <[email protected]>",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.18.2"
}
}
The second file is our sample app, a simple “hello world” server. Still inside
src/
, add the following contents to server.js
:
'use strict';
const express = require('express')
const app = express()
const port = 8080
const host = '0.0.0.0'
app.get('/', (req, res) => {
res.send('Hello World from inside the ROCK!');
});
app.listen(port, host, () => {
console.log(`Running on http://${host}:${port}`);
});
Next, we’ll setup the Rockcraft project. In the original empty folder, create
an empty file called rockcraft.yaml
. Then add the following snippets, one
after the other:
Add the metadata that describes your ROCK, such as its name and licence:
name: my-node-app
base: [email protected]
version: '1.0'
summary: A ROCK that bundles a simple nodejs app
description: |
This ROCK bundles a recent node runtime to serve a simple "hello-world" app.
license: GPL-3.0
platforms:
amd64:
Add the container entrypoint, as a Pebble service:
services:
app:
override: replace
command: node server.js
startup: enabled
on-success: shutdown
on-failure: shutdown
working-dir: /lib/node_modules/node_web_app
Finally, add a part that describes how to build the app created in the src/
directory using the npm
plugin:
parts:
app:
plugin: npm
npm-include-node: True
npm-node-version: "21.1.0"
source: src/
The whole file then looks like this:
name: my-node-app
base: [email protected]
version: '1.0'
summary: A ROCK that bundles a simple nodejs app
description: |
This ROCK bundles a recent node runtime to serve a simple "hello-world" app.
license: GPL-3.0
platforms:
amd64:
services:
app:
override: replace
command: node server.js
startup: enabled
on-success: shutdown
on-failure: shutdown
working-dir: /lib/node_modules/node_web_app
parts:
app:
plugin: npm
npm-include-node: True
npm-node-version: "21.1.0"
source: src/
Pack the ROCK with Rockcraft¶
To build the ROCK, run:
rockcraft pack
At the end of the process, a new ROCK file should be present in the current directory:
ls my-node-app_1.0_amd64.rock
Run the ROCK in Docker¶
First, import the recently created ROCK into Docker:
sudo /snap/rockcraft/current/bin/skopeo --insecure-policy copy oci-archive:my-node-app_1.0_amd64.rock docker-daemon:my-node-app:1.0
Since the ROCK bundles a web-app, we’ll first start serving that app on local port 8000:
docker run --name my-node-app -p 8000:8080 my-node-app:1.0
The output will look similar to this, indicating that Pebble started the app
service:
2023-10-30T12:37:33.654Z [pebble] Started daemon.
2023-10-30T12:37:33.659Z [pebble] POST /v1/services 3.878846ms 202
2023-10-30T12:37:33.659Z [pebble] Started default services with change 1.
2023-10-30T12:37:33.663Z [pebble] Service "app" starting: node server.js
2023-10-30T12:37:33.864Z [app] Running on http://0.0.0.0:8080
Next, open your web browser and navigate to http://localhost:8000
. You
should see a blank page with a “Hello World from inside the ROCK!” message.
Success!
You can now stop the running container by either interrupting it with CTRL+C or by running the following in another terminal:
docker stop my-node-app
References¶
The sample app code comes from the “Hello world example” Express tutorial, available at https://expressjs.com/en/starter/hello-world.html.