Time to “Hello, World”: running Node.js on VMs, Containers, Apps, and Functions — Part 2

Building with virtual machines

This article is a part of the series: Part 1 (overview), Part 2 (VMs), Part 3 (containers), Part 4 (apps) and Part 5 (functions & summary).

“Hello, World” on Compute Engine

Compute Engine lets you create and run virtual machines on Google infrastructure. Compute Engine provides control of every component but also assumes it’s your responsibility to keep things running. With VMs, you obviously need to go ahead and install/configure your own web hosting stack from scratch (and also decide how to provide for load balancing and scalability, from a variety of options.)

The GCP documentation looks extremely useful, but who starts by reading the manual? Google Search to the rescue: “google compute engine create a vm”, “google compute engine ssh into vm”, “install node.js linux”, “hello world node.js”, “hello world node.js google compute engine”…

Plan of attack:

  1. Create and set up a VM instance
  2. Install Node.js and Express
  3. Code “Hello World” application
  4. Expose the VM & app to external traffic
  5. Assess scaling with Compute Engine
“Hello, World” on Compute Engine

1) Create and set up a VM instance

Navigate to VM Instances page in Google Cloud Console and go through the setup process. (I selected one of the most basic VMs since my app isn’t really going to do anything beyond listening on a port and returning a string.)

  • Instance name: changed to helloworld-vm
  • Machine type: changed to small (1 shared vCPU, 1.7 GB memory)
  • Zone: changed to us-west-a (I am based in Seattle, so selected one of the ‘west’ options available)
  • Boot disk: Google Debian GNU/Linux 9 (default)
  • Firewall: checked to allow both HTTP and HTTPS traffic

The VM creation wizard gave me a pricing estimate, among other things. Neat. My “Hello World” application would cost me approximately $14 per month even if it just sat there idle and served no traffic.

Hit the Create button. The VM instance is up and running in literally a few seconds. Wow!

Clicking around Google Cloud Console, you’ll see that one of the options is to SSH into your newly set up VM directly from your web browser:

For command line access using Cloud SDK (gcloud), there is a menu that generates the appropriate command:

$ gcloud compute --project "helloworld-mtthw" ssh --zone "us-west1-a" "helloworld-vm"
...
melnykdima@helloworld-vm: ~$

2) Install Node.js & Express

$ sudo apt-get update
$ sudo apt-get install nodejs
$ sudo apt-get install npm
...
E: Unable to locate package npm

Hmm… let’s Google the errorInstalling Node.js Tutorial: Debian Linux:

$ sudo curl -sL https://deb.nodesource.com/setup_8.x | bash -
...
Could not open lock file /var/lib/apt lists/lock - open (13: Permission denied)

Aha! Missing sudo:

$ sudo curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
$ sudo apt-get install -y nodejs

Let’s double check the Node version:

$ nodejs --version
v8.10.8

In reality, it took me more iterations to complete this seemingly simple step. For example, I made a mistake while trying to fix the “unable to locate package npm” error and ended up with Debian’s default version of Node (v4.8.2 at the time of writing this article), so I had to go back and restore my sources.list file and re-run the installation process.


3) Code “Hello World” and start a Node server

Interactively create a package.json file using npm-init:

$ npm init

Install the Express.js web application framework and save it to the list of dependencies. I decided to start using Express right away in anticipation of additional experiments with REST APIs (outside of the scope of this blog post).

$ npm install express --save

Let’s code a Hello World application in Node.js with Express:

$ vim hello.js
$ node hello.js
Example app listening on port 3000!

4) Expose the app to the outside world

I search on “google compute engine open firewall ports”, which brings me to StackOverflow. Then I open port 3000 for both http and https using Cloud Console (Networking > VPC Network):

I attempt to connect by clicking the link and appending port 3000 to my VM’s IP:

Hmm… let’s double check everything… ping the VM, revisit the firewall settings, make sure the Node server is still running… must be something simple… HTTPS? I do a Google search on “node js express http https”… aha! (I could have guessed there will be additional https setup involved with SSL certificates.)

Since my goal was to stand up a simple “Hello World”, I simply change my URL from “https” to “http” and called the GCE/VM part done:

Reliability and scaling concerns aside, my app is running on a single VM instance in GCE. Woohoo!

Note: shortlist of steps required to run Node resiliently in production on a VM:

  1. Run on a production port (as opposed to sharing 3000 to the world)
  2. Start Node on server startup
  3. Handle crashes (restart using forever or pm2)
  4. Create logs

5) What’s involved with scaling VMs

At some point in your application development process, you may want to start thinking about scaling your application so that it can respond quickly and appropriately to your customer requests, without overloading your VM instances.

Compute Engine does offer load balancing and autoscaling for groups of instances but it requires additional setup, maintenance, as well as general understanding of scalable web architectures and distributed systems design. This 10 minute video primer will take you through the basic steps involved with scaling your VM instances on Compute Engine. And for those of you who might be interested in learning more about the fundamentals of scaling web applications, I found this Udacity playlist very helpful (the whiteboarding session will take you through Reddit’s scaling journey).


6) Time check & getting started resources

Image source

It took me a good 4–5 hours to figure out how to run “Hello World” on VMs. I was initially anticipating that most of my time would go into skimming through the fundamentals of how people build web apps in 2018, but I ended spending at least half of it solving basic Linux setup issues. Granted, you could do this much faster if you know all your Linux commands by heart or develop software for a living. Although if you compare 4.5 hours to the time it would take you to order and configure a real physical server, it still is a great deal!

Useful getting started resources:


Continue on to:

  • Part 3: building with Docker containers (Kubernetes Engine)
  • Part 4: building on top of PaaS (App Engine)
  • Part 5: building with FaaS (Cloud Functions) & summary