-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The tutorial builds a simple "hello world" webapp and showcases using a package-repository to install newer node. Fixes #369
- Loading branch information
Showing
7 changed files
with
266 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
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/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
'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}`); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
|
||
summary: donejs tutorial | ||
|
||
execute: | | ||
# [docs:install-rockcraft] | ||
sudo snap install rockcraft --classic --edge | ||
# [docs:install-rockcraft-end] | ||
# [docs:build-rock] | ||
rockcraft pack | ||
# [docs:build-rock-end] | ||
# [docs:check-rock] | ||
ls my-node-app_1.0_amd64.rock | ||
# [docs:check-rock-end] | ||
# test container execution | ||
docker images | ||
# [docs:skopeo-copy] | ||
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 | ||
# [docs:skopeo-copy-end] | ||
rm *.rock | ||
docker images my-node-app:1.0 | ||
# When the container is started it launches the app listening on port 8080 | ||
# NOTE: the convoluted code here is to expose the "docker run" line cleanly | ||
# to the documentation that uses it. | ||
cat <<EOF > run-container.sh | ||
# [docs:run-container] | ||
docker run --name my-node-app -p 8000:8080 my-node-app:1.0 | ||
# [docs:run-container-end] | ||
EOF | ||
bash run-container.sh & | ||
# Wait for a bit for the app to come online | ||
retry -n 5 --wait 2 curl localhost:8000 | ||
curl localhost:8000 | MATCH "Hello World from inside the ROCK" | ||
# [docs:stop-container] | ||
docker stop my-node-app | ||
# [docs:stop-container-end] | ||
restore: | | ||
rm -f ./*.rock | ||
docker rm -f my-node-app | ||
docker rmi -f my-node-app:1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
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: | ||
|
||
.. literalinclude:: code/node-app/task.yaml | ||
:language: bash | ||
:start-after: [docs:install-rockcraft] | ||
:end-before: [docs:install-rockcraft-end] | ||
:dedent: 2 | ||
|
||
|
||
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: | ||
|
||
.. literalinclude:: code/node-app/src/package.json | ||
:caption: package.json | ||
:language: json | ||
|
||
The second file is our sample app, a simple "hello world" server. Still inside | ||
``src/``, add the following contents to ``server.js``: | ||
|
||
.. literalinclude:: code/node-app/src/server.js | ||
:caption: server.js | ||
:language: javascript | ||
|
||
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: | ||
|
||
.. literalinclude:: code/node-app/rockcraft.yaml | ||
:caption: rockcraft.yaml | ||
:language: yaml | ||
:start-at: name: my-node-app | ||
:end-at: amd64: | ||
|
||
Add the container entrypoint, as a `Pebble`_ service: | ||
|
||
.. literalinclude:: code/node-app/rockcraft.yaml | ||
:caption: rockcraft.yaml | ||
:language: yaml | ||
:start-at: services: | ||
:end-at: 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: | ||
|
||
.. literalinclude:: code/node-app/rockcraft.yaml | ||
:caption: rockcraft.yaml | ||
:language: yaml | ||
:start-at: parts: | ||
:end-at: source: src/ | ||
|
||
The whole file then looks like this: | ||
|
||
.. literalinclude:: code/node-app/rockcraft.yaml | ||
:caption: rockcraft.yaml | ||
:language: yaml | ||
|
||
|
||
Pack the ROCK with Rockcraft | ||
---------------------------- | ||
|
||
To build the ROCK, run: | ||
|
||
.. literalinclude:: code/node-app/task.yaml | ||
:language: bash | ||
:start-after: [docs:build-rock] | ||
:end-before: [docs:build-rock-end] | ||
:dedent: 2 | ||
|
||
At the end of the process, a new ROCK file should be present in the current | ||
directory: | ||
|
||
.. literalinclude:: code/node-app/task.yaml | ||
:language: bash | ||
:start-after: [docs:check-rock] | ||
:end-before: [docs:check-rock-end] | ||
:dedent: 2 | ||
|
||
Run the ROCK in Docker | ||
---------------------- | ||
|
||
First, import the recently created ROCK into Docker: | ||
|
||
.. literalinclude:: code/node-app/task.yaml | ||
:language: bash | ||
:start-after: [docs:skopeo-copy] | ||
:end-before: [docs:skopeo-copy-end] | ||
:dedent: 2 | ||
|
||
Since the ROCK bundles a web-app, we'll first start serving that app on local | ||
port 8000: | ||
|
||
.. literalinclude:: code/node-app/task.yaml | ||
:language: bash | ||
:start-after: [docs:run-container] | ||
:end-before: [docs:run-container-end] | ||
:dedent: 2 | ||
|
||
The output will look similar to this, indicating that Pebble started the ``app`` | ||
service: | ||
|
||
.. code-block:: text | ||
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: | ||
|
||
.. literalinclude:: code/node-app/task.yaml | ||
:language: bash | ||
:start-after: [docs:stop-container] | ||
:end-before: [docs:stop-container-end] | ||
:dedent: 2 | ||
|
||
References | ||
---------- | ||
|
||
The sample app code comes from the "Hello world example" Express tutorial, | ||
available at https://expressjs.com/en/starter/hello-world.html. | ||
|
||
|
||
.. _`Pebble`: https://github.com/canonical/pebble | ||
.. _`NodeSource`: https://nodesource.com/ |