Tutorials > How to automate the deployment of a Node.js app with Shipit on CentOS 7

How to automate the deployment of a Node.js app with Shipit on CentOS 7

Published on: 03 December 2020

CentOS Development Git Node.js

Shipit is a tool that configures the deployment of Node.js applications on remote servers. Thanks to Orchestrator and other packages such as OpenSSH, it allows you to configure automatic tasks and better manage the publication of Node.js applications.

In this tutorial you will learn how to configure an automatic process to transfer a sample application from your local machine to the remote server, using the Shipit development tool.

Prerequisites

To get started, connect to your server via an SSH connection. If you haven't done so yet, following our guide is recommended to  connect securely with the SSH protocol. In case of a local server, go to the next step and open the terminal of your server.

Before proceeding to develop our sample application, get Git and Node.js installed on your machine. If needed, visit our guides on  how to install Git  and  how to install Node.js  for more information.

Creating the repository on GitHub

Shipit allows you to synchronize a Git repository from a development machine to a remote server. In this example the service provided by github.com will be used to create our repository and allow it to be synchronized.

In case you don't want to use github.com, the commands used in the following guide are compatible with any other remote Git repository.

To create your repository visit the following url:

https://github.com/new
 

Fill in the fields required by the site, using text with no spaces or special characters as ‘Repository name’. In this tutorial, ‘shipit-test’ will be used.

Once completed, use the "Create repository" button to complete the operation.

Creating Project

Using your machine proceed to clone the newly created repository using the command shown below and replace the following fields as follows:

git clone [email protected]:[USERNAME_GITHUB]/[REPOSITORY].git
 

In this case:

git clone [email protected]:shipit-user/shipit-test.git
 

Then, go into the newly created folder and start an empty project with npm:

cd shipit-test
 
npm init -y
 

Proceed by installing the Express framework and Shipit dependencies:

npm i --save express
 
npm i --save-dev shipit-cli shipit-deploy shipit-shared
 

At this point, a sample application can be created to verify the correct functioning of Shipit. In this tutorial the Express ‘Hello world’ template will be used:

const express = require('express')
 const app = express()
 const port = 3000
 
 app.get('/', (req, res) => {
 res.send('Hello World!')
 })
 
 app.listen(port, '0.0.0.0', () => {
 console.log(`Example app listening at http://localhost:${port}`)
 })
 

Save the list above in a new file called ‘index.js’ using your favorite text editor.

Then, continue by creating a second file, called ‘shipitfile.js’ with the following content:

module.exports = shipit => {
 // Load shipit-deploy tasks
 require('shipit-deploy')(shipit)
 
 shipit.initConfig({
 default: {
 deployTo: '/var/node/shipit-test',
 repositoryUrl: 'https://github.com/[USERNAME_GITHUB]/[REPOSITORY].git',
 },
 staging: {
 servers: 'deploy@[SERVER_IP]',
 },
 })
 }
 

Change appropriately the fields above with the name of your GitHub user, the name of the repository previously created and the address of the remote server.

Add the newly created files to the Git repository via the command:

git add index.js shipitfile.js package.json
 

Then, proceed with the creation of a commit and submit the changes:

git commit -m "Setup"
git push -u origin master
 

Configuring Server in production

When all the steps above have been completed, proceed by configuring the remote server where to deploy your application.

First, proceed with the installation of rsync, a package required by Shipit to synchronize the files between your development and the production machines:

yum install rsync -y
 

Then, proceed with the creation of a unix user to be used through ShipIt for the deployment:

useradd --shell /usr/bin/bash deploy
 

Set a password for the newly created user:

passwd deploy
 

Then, create a folder to deploy and assign permissions for the newly created user:

mkdir /var/node
 
chown deploy:deploy /var/node
 

Then, install the latest version of Node.js via commands:

curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash -
 
yum install nodejs -y
 

Verify the correct installation of Node.js by running the command:

node -v
v12.18.3
 

Deploy the application

At this point, proceed with the first deployment from your development machine, by running the command below, in the project folder previously created:

npx shipit staging deploy
 

After running the command, enter the remote server password several times, as asked by the deployment process, to perform all the necessary operations.

During this process, a series of information on the status of the deployment will be printed on the screen. Once completed, a message like the following will be shown:

Finished 'deploy:finish' after 178 μs
 

By connecting to the remote machine, verify the deployment by running the command:

ls /var/node/shipit-test/current/
 
index.js package.json REVISION shipitfile.js
 

As shown above, all the necessary files for the project to function properly will be shown.

Deployment optimization and first start

So far, you have configured Shipit to deploy the updated sources to the remote server. However, to make the most of Shipit's potential, use its event system to start your application after deployment.

First, install PM2 on the remote server: a software used to keep node processes running as daemons.

Then, launch on the remote server:

npm i -g pm2
 

Then, edit the shipitfile.js file by adding a new task called “pm2-setup” as follows:


 shipit.blTask('pm2-setup', async () => {
 
 // Eliminate potential previous demons 
 await shipit.remote(`pm2 delete -s shipittest || :`);
 
 // Launch the npm package installation of the present deployment directory
 await shipit.remote(`cd ${shipit.currentPath} && npm i`);
 
 // Start the demon through pm2
 await shipit.remote(
 `pm2 start --name shipittest ${shipit.currentPath}/index.js --env production`
 );
 
 });
 

Once this new task has been created, attach it to the "deployed" event:

shipit.on('deployed', async () => {
 shipit.start('pm2-setup');
 });
 

The final file should be as follows:

module.exports = shipit => {
 // Load shipit-deploy tasks
 require('shipit-deploy')(shipit)
 
 shipit.initConfig({
 default: {
 deployTo: '/var/node/shipit-test',
 repositoryUrl: 'https://github.com/[USERNAME_GITHUB]/[REPOSITORY].git',
 },
 staging: {
 servers: 'deploy@[SERVER_IP]',
 },
 })
 
 shipit.blTask('pm2-setup', async () => {
 
 // Eliminate potential previous demons
 await shipit.remote(`pm2 delete -s shipittest || :`);
 
 // Launch npm packages installation of the present deployment directory 
 await shipit.remote(`cd ${shipit.currentPath} && npm i`);
 
 // Start the demon through pm2
 await shipit.remote(
 `pm2 start --name shipittest ${shipit.currentPath}/index.js --env production`
 );
 
 });
 
 shipit.on('deployed', async () => {
 shipit.start('pm2-setup');
 });
 }
 
 

Then, proceed by relaunching the deployment from your development spot:

npx shipit staging deploy
 

If everything works correctly, your application will respond to the address of the remote machine, on port 3000. For example:

http://[SERVER_IP]:3000
 

Conclusion

In this tutorial, only some of the potential offered by Shipit has been used. Shipt is a tool that allows you to deploy and automate various tasks on your remote servers. For more information on its use, consult the official guides on GitHub:

https://github.com/shipitjs/shipit
 
https://github.com/shipitjs/shipit/tree/master/packages/shipit-deploy
 

Shipit also allows you to automate many operations between local and remote machines, add different tasks and events according to the needs of your application.

For more information on the PM2 package, viewing this documentation is recommended:

https://pm2.keymetrics.io/docs/usage/pm2-doc-single-page/