Node Js Builder

Introduction

In this post I’ll quickly take you through the process of copying the source code of a NodeJS project into a virtual machine(VM) and running it using Vagrant. This provides a neat way to perform a sanity check on your project and see if you can build & run it from scratch on a fresh machine. You can use the VM with production environment if possible to get early feedback on whether your code will deploy successfully outside of your development machine or not. You can also use the VM to resolve “works on my machine” arguments between team members. Check my previous post for more details on Vagrant.

Basic terminology:

Installing Vagrant & Virtual

In this post I’ll use Virtualbox to run the VMs but remember that Vagrant also supports alternatives like VMWare, Hyper-V, etc.

Install Vagrant & Virtualbox for your operating system.

For example, you can run the following commands to install them on most Ubuntu versions:

Virtualbox

Copy to Clipboard

Replace virtualbox-6.1 with the latest version available for your operating system.

Vagrant

Copy to Clipboard

Replace 2.2.13 with the latest version of Vagrant available for your operating system. Make sure that you have /usr/local/bin in your PATH variable.

Clone NodeJS code repository

If you’ve a NodeJS project feel free to use it otherwise you can use the project in basic-nodejs folder that I’ve created for the purposes of this post.

Copy to Clipboard

Create a Vagrantfile

The command vagrant init creates a file called Vagrantfile which contains example configuration and comments explaining some of the things that you can customise in it. It also creates a folder named .vagrant that’s managed by Vagrant; you should add it to the .gitignore file.

vagrant init

Once you’re done reading all the comments in the Vagrantfile, replace the contents in the file with the following code(also available in Vagrantfile.example file):

Copy to Clipboard

Let us look at the above code in more detail.

We’re asking Vagrant to use a box called generic/ubuntu1804 as the base operating system to create the VM. You can find vagrant boxes for all kinds of operating systems – some are bare-bones, some install utilities & build tools on top of the OS. You can check Vagrant Cloud website to find more vagrant boxes. You can create your own custom boxes also.

We’ll be running a web API over port 3000 inside the VM which we can access from our host machine in several ways. I’m going to use private_network mode in this post.

Copy to Clipboard

This network mode can be used to map the port number of an app running inside the VM to the same port number on a specific ip address specified by you e.g. 192.168.33.100 in our case. The app running on port 3000 inside the VM can then be accessed from the host machine by using http://192.168.33.100:3000.

To use human-friendly names, you can map the ip address of the virtual machine to a name in your /etc/hosts file:

Copy to Clipboard

If you do this, you should be able to access the app using http://nodejs-app:3000 also as the address.

Vagrant also supports
public_network & forwarded_ports network modes.

Copy to Clipboard

Next we set RAM for the virtual machine to be 512MB. This is enough for most operating systems when run in headless mode. You can check memory usage by running top command when inside the VM. Use a higher value like 1024 or 2048 if you need it. You can also use vm.cpus = 2 to set the number of cpu cores that the VM can use to 2 in case you have 4 or more cores on your host machine.

Copy to Clipboard

The folder where Vagrantfile exists is by default mapped to /vagrant path inside the virtual machine. I like to map just my project folder on the host machine to a folder with the same name inside my home folder in the VM. Note that Vagrant creates a user called vagrant and home folder for that user called /home/vagrant automatically.

Copy to Clipboard

Finally, we use Vagrant’s shell provisioner to run a bash script called install-node.sh present in the root folder of the host machine. We put commands to install nvm, nodejs & configure a few things in this shell file; you can customise it based on your needs & the Vagrant box you’re using. Read more about shell provisioner.

We run the script as a non-root user by using privileged: false, which is the recommended way to install nvm. Vagrant runs the file provisioner as root user by default.

Contents of install-node.sh file:

Note: Check latest instructions to install nvm.

Copy to Clipboard

Build & run the nodejs application

vagrant up will download the vagrant box specified in the Vagrantfile, create a VM using Virtualbox, set RAM to 512MB, configure the networking as per our config.vm.network lines, and finally run our install-node.sh script to install nodejs. Once the virtual machine is up, we can SSH into the VM and build the project.

Copy to Clipboard

After you SSH into the VM, you can change the folder to our nodejs project and run all the npm commands that we can otherwise run from our host machine. Remove node_modules folder before running other commands if you want a clean code base to work with on the guest machine. You can also clone your project’s repository inside the guest machine using git clone command(copy the private ssh key to guest machines ~/.ssh folder if necessary using Vagrant’s file provisioner).

After you run npm run start, you should be able to access the app at http://localhost:3000 from inside the VM(e.g. using curl) or at http://192.168.33.100:3000 from the host machine. You can also access it at http://nodejs-box:3000 on your host machine if you have added the domain mapping in your /etc/hosts/ file as explained above.

You can simplify the above process by passing the commands to vagrant ssh command directly:

Copy to Clipboard

The above command will connect to the VM over SSH, run the commands, and then disconnect automatically. You can run the production version by building the project on host machine using production settings, copying the dist or build folder containing generated Javascript files to the VM and running the application using node command. Or simply do the following:

Copy to Clipboard

If you have more steps to perform, you can put all the commands in a bash script and run that script instead. For example, create a
file called run.sh in the root folder on the host machine:

Copy to Clipboard

Run the script via SSH:

Copy to Clipboard

Conclusion

Vagrant is one of the simplest IaC tools that a developer can learn, most of the learning curve actually comes from dealing with Virtualbox & guest OS related issues – Vagrant itself is pretty easy to learn. You can likely read most of its documentation in a day or two! It has a number of use cases, this post demostrated just one of them, and I hope I can showcase one more example use case in a future post.

References