Easy nodejs
deployment
This article is going to explore how to deploy a nodejs
application on a traditional linux
server — in a non-cloud environment. Even though the use case is Ubuntu, any Linux distro or mac
would work perfectly fine.
For information on deploying on non-traditional servers, read: “Deploying
nodejs
applications”. For zero-downtime knowledge, read “How to achieve zero downtime deployment withnodejs
“
In this article we will talk about:
- Preparing
nodejs
deployable releases - Configuring
nodejs
deployment environment - Deploying
nodejs
application on bare metal Ubuntu server - Switching on
nodejs
application to be available to the world ~ addingnginx
for the reverse proxy to make the application available to the world - post-deployment support — production support
Even though this blog post was designed to offer complementary materials to those who bought my Testing
nodejs
Applications book book, the content can help any software developer to level up their knowledge. You may use this link to buy the book.
Preparing a deployable release
There are several angles to look at release and deployment from. There are also several ways to release nodejs
code, npm
and tar
for instance, and that depending on the environment in which the code is designed to run. Amongst environments, server-side, universal, or command line are classic examples.
In addition, we have to take a look from a dependency management perspective. Managing dependencies at deployment time has two vectors to take into account: whether the deployment happens on online or offline.
For the code to be prepared for release, it has to be packaged. Two methods of packaging
nodejs
software, amongst other things, are managed packaging and bundling. More on this is discussed here
As a plus, versioning should be taken into consideration when preparing a deployable release. The versioning that is a little common circulation is SemVer.
Configuring deployment environment
Before we dive into deployment challenges, let's look at key software and configuration requirements.
As usual, first-time work can be hard to do. But the yield should be then predictable, flexible to improvement, and capable of being built-upon for future deployments. For context, the deployment environment we are talking about in this section is the production environment.
Two key configurations are an nginx
reverse proxy server and nodejs
. But, “Why coupling nodejs
server to an nginx
reverse proxy server”? The answer to this question is two folds. First, both nodejs
and nginx
are single-threaded non-blocking reactive systems. Second, the wide adoption of these two tools by the developer community makes it an easy choice, from both influence and availability of collective knowledge the developer community shares via forums/blogs and popular QA sites.
How to install
nginx
server ~ [there is an article dedicated to this](). How to configurenginx
as anodejs
application proxy server ~ there is an article dedicated to this.
Additional tools to install and configure may include: mongod
database server, redis
server, monit
for monitoring, upstart
for enhancing the init
system.
There is a need to better understand the tools required to run nodejs
application. It is also our responsibility as developers to have a basic understanding of each tool and the roles it plays in our project, in order to figure out how to configure each tool.
Download source code
Starting from the utility perspective, there is quite a collection of tools that are required to run on the server, alongside our nodejs
application. Such software needs to be installed, and updated ~ for patch releases, and upgraded ~ to new major versions to keep the system secure and capable(bug-free/enhanced with new features).
From the packaging perspective, both supporting tools and nodejs
applications adhere to a packaging strategy that makes it easy to deploy. When packaging is indeed a bundle, wget
/curl
can be used to download binaries. When dealing with discoverable packages, npm
/yarn
/brew
can also be used to download our application and its dependencies. Both operation yield same outcomes, which is un-packaging, configuration and installation.
To deploy versioned nodejs
application on bare metal Ubuntu server ~ understanding file system tweaks such as symlink-ing for faster deployments can save time for future deployments.
#first time on server side
$ apt-get update
$ apt-get install git
#updating|upgrading server side code
$ apt-get update
$ apt-get upgrade
$ brew upgrade
$ npm upgrade
# Package download and installs
$ /bin/bash -c "$(curl -fsSL https://url.tld/version/install.sh)"
$ wget -O - https://url.tld/version/install.sh | bash
# Discoverable packages
$ npm install application@next
$ yarn add application@next
$ brew install application
_Example: _
The command above can be automated via a scheduled task. Both
npm
andyarn
support the installation of applications bundled in a.tar
file. See an example of a simple script source. We have to be mindful to clean up download directories, to save disk space.
Switching on the application
It sounds repetitive, but running npm start
does not guarantee the application to be visible outside the metal server box the application is hosted on. This magic belongs to the nginx
reverse proxy we were referring to in earlier paragraphs.
A typical nodejs
application needs to start one or more of the following services, each time to reboot the application.
# symlinking new version to default application path
$ ln -sfn /var/www/new/version/appname /var/www/appname
$ service nginx restart #nginx|apache server
$ service redis restart #redis server
$ service restart mongod #database server in some cases
$ service appname restart #application itself
Example:
PS: Above services are managed with
uptime
Adding nginx
reverse proxy makes the application available to the outside world. Switching on/off the application can be summarized in one command: service nginx stop
. Likewise, to switch off and back on can be issued in one command: service nginx restart
.
Post-deployment support
Asynchronous timely tasks can be used to resolve a wide range of issues. Background tasks such as fetching updates from third-party data providers, system health check, and notifications, automated software updates, database cleaning, cache busting, scheduled expensive/CPU intensive batch processing jobs just to name a few.
It is possible to leverage existing asynchronous timely OS-provided tasks processing infrastructure to achieve any of the named use cases, as it is true for third-party tools to do exactly the same job.
Rule of thumb
The following is a mental model that can be applied to the common use cases of releases. It may be basic for DevOps professionals, but useful enough for developers doing some operations work as well.
- Prepare deployable releases
- Update and install binaries ~ using
apt
,brew
etc. - Download binaries ~ using
git
,wget
,curl
orbrew
symlink
directories(/log
,/config
,/app
)- Restart servers and services ~
redis
,nginx
,mongodb
andapp
- When something goes bad ~ walk two steps back. That is our rollback strategy.
This model can be refined, to make most of these tasks repeatable and automated, deployments included.
Conclusion
In this article, we revisited quick easy, and most basic nodejs
deployment strategies. We also revisited how to expose the deployed applications to the world using nginx
as a reverse proxy server. There are additional complimentary materials in the “Testing nodejs
applications” book.
References
- Testing
nodejs
Applications book - How to set up CI/CD Pipeline for a
nodejs
app with Jenkins ~ Moshe Ezderman – Medium - “Build your dependencies into your deployable packages”