Learning Outcomes
- distinguish between real and virtual machines
- configure and provision a VM in the public cloud
- deploy a Node.js application to virtual machine
- use a daemon process manager to keep a Node.js application alive
Resources
- Virtualization Explained (video)
- slides
- narated slides (video)
Lab
Video walkthrough of this lab.
Create a Node.js Application
Start the Google Cloud Shell.
In the terminal, use the Express application generator to create an application skeleton:
npx express-generator --view=ejs myapp
Change to the application directory:
cd myapp
Install the dependencies:
npm install
Run the application:
PORT=8080 DEBUG=myapp:* npm start
Preview the application using the web preview button .
Stop the application (CTRL-C
).
Make a visible change to myapp/views/index.ejs
and save the changes.
Re-start the application:
PORT=8080 DEBUG=myapp:* npm start
Refresh the application in the browser and confirm the change took effect.
Stop the application (CTRL-C
).
Create a Firewall Rule
From the Google Cloud console page, go to “NETWORKING | VPC network | Firewall”. You may be asked to enable the compute engine API. Just go ahead and enable it.
Click on the “CREATE FIREWALL RULE” button.
- For “Name”, enter “allow-http-8080”.
- Leave “Logs” in the “Off” setting.
- Leave “Network” at “default”
- Leave “Priority” at “1000”.
- Leave “Direction of traffic” at “Ingress”.
- Leave “Action on match” at “Allow”.
- For “Targets”, choose “Specified target tags”.
- For “Target tags”, enter “http-server-8080”.
- Leave “Source filter” at “IP ranges”.
- For “Source IP ranges”, enter “0.0.0.0/0”.
- Leave “Second source filter” at “None”.
- Leave “Protocols and ports” at “Specified protocols and ports”.
- Check “tcp” and enter “8080”.
Click on the “CREATE” button.
Create a Virtual Machine
From the Google Cloud console page, go to “COMPUTE | Compute Engine | VM instances”.
Click on the “CREATE INSTANCE” button.
- For “Name”, enter “lab1”.
- For “Region”, choose either the region geographically closest to you (if you are in Vancouver, this would be “us-west1 (Oregon)”) or “northamerica-northeast1 (Montreal)”.
- Leave “Zone” alone.
- For “Machine configuration | Series”, choose “N1”.
- For “Machine configuration | Machine type”, choose “f1-micro”.
- Confirm that “Boot disk” is set to “Debian GNU/Linux 10 (buster)”.
- Click the “Management, security, disks, networking, sole tenancy” link to expand the available options.
- Click on the “Networking” tab.
- For “Network tags”, enter “http-server-8080”.
Click on the “Create” button.
Install Node.js on the Virtual Machine
Back in the Cloud Shell terminal, verify that the new virtual machine instance is running:
(You may be asked to authorize the API call).
gcloud compute instances list
SSH into the new virtual machine:
gcloud compute ssh lab1 --zone YOUR_ZONE_GOES_HERE
(It will proabably generate a SSH key first. You can leave the passphrase blank.)
Install Node.js:
curl -sL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
Log out of the virtual machine (CTRL-D
).
Deploying a Node.js Application to a Virtual Machine
Delete the node_modules directory:
rm -r node_modules
Move to the parent directory:
cd ..
Copy the application to the virtual machine:
gcloud compute scp --recurse myapp lab1: --zone YOUR_ZONE_GOES_HERE
SSH back into the new virtual machine:
gcloud compute ssh lab1 --zone YOUR_ZONE_GOES_HERE
Change to the application directory:
cd myapp
Install the dependencies:
npm install
Run the application:
PORT=8080 DEBUG=myapp:* npm start
In a new tab, browse to the application using the external IP address for the virtual machine (http://NNN.NNN.NNN.NNN:8080
).
Stop the application (CTRL-C
).
Log out of the virtual machine (CTRL-D
).
Crash a Node.js Application
In myapp/views/index.ejs
add links to the home page as follows:
<p><a href="/">Home</a></p>
<p><a href="/crash">Crash</a></p>
Create myapp/routes/crash.js
as follows:
var express = require('express');
var router = express.Router();
function crash() {
process.exit();
}
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Crash!' });
setTimeout( crash, 4000 );
});
module.exports = router;
In myapp/app.js
, require the “crash” router:
var crashRouter = require('./routes/crash');
and configure the app to use the new router:
app.use('/crash', crashRouter);
Re-start the application:
cd myapp
npm install
PORT=8080 DEBUG=myapp:* npm start
Preview the running application in the browser and follow the “Crash” link to “crash” the application. Wait 4 seconds; follow the “Home” link in the page. The page should not load because the application has stopped.
Remove the node_modules
directory and copy the modified application to the virtual machine:
rm -r node_modules
cd ..
gcloud compute scp --recurse myapp lab1: --zone YOUR_ZONE_GOES_HERE
SSH back into the virtual machine:
gcloud compute ssh lab1 --zone YOUR_ZONE_GOES_HERE
Change to the application directory:
cd myapp
Run the application:
PORT=8080 DEBUG=myapp:* npm start
In a new tab, browse to the application using the external IP address for the virtual machine (http://NNN.NNN.NNN.NNN:8080
). Follow the “Crash” link to “crash” the application. Wait 4 seconds; follow the “Home” link in the page. The page should not load because the application has stopped.
Use a Daemon Process Manager to Keep a Node.js Application Alive
Install the PM2 daemon process manager:
sudo npm install pm2@latest -g
Change to the bin
directory of the application:
cd bin
Start the application using the process manager:
PORT=8080 DEBUG=myapp:* pm2 start www
View the logs for the running application:
pm2 logs
Browse to the application using the external IP address for the virtual machine (http://NNN.NNN.NNN.NNN:8080
). Follow the “Crash” link to “crash” the application. Watch the log entries and notice how the process manager automatically restarts the application. Follow the “Home” link in the page and observe how it now works correctly.
Stop the logging application (CTRL-C
).
Log out of the virtual machine (CTRL-D
).