Deploying to Production

Now that you have completed your first React application, it is time to learn how to deploy it to the world. For this purpose, we will use the cloud service called DigitalOcean.

In this chapter, you will learn how to deploy your React application using Node.js and nginx on an Ubuntu server from DigitalOcean.

In this chapter, we will cover the following topics:

  • Creating a DigitalOcean Droplet and configuring it
  • Configuring nginx, PM2, and a domain
  • Implementing CircleCI for continuous integration

Technical requirements

To complete this chapter, you will need the following:

  • Node.js 12+
  • Visual Studio Code

Creating our first DigitalOcean Droplet

I have used DigitalOcean for the last six years and I can say that it is one of the best cloud services I have tried, not just because of the affordable costs, but also because it is super easy and fast to configure, and the community has a lot of updated documentation to fix most of the common issues related to server configuration.

At this point, you will need to invest some money to get this service. I will show you the cheapest way to do this, and if in the future you want to increase the power of your Droplets, you will be able to increase the capacity without redoing the configuration. The lowest price for the very basic Droplet is $5.00 per month ($0.007 per hour).

We are going to use Ubuntu 20.04 (but feel free to use the latest version 21.04); you will need to know some basic Linux commands to be able to configure your Droplet. If you're a beginner using Linux, don't worry—I'll try to show you each step in a very easy way.

Signing up to DigitalOcean

If you don't have a DigitalOcean account, you can sign up at https://cloud.digitalocean.com/registrations/new.

You can sign up with your Google account, or by registering manually. Once you register with Google, you will see the billing info view, as follows:

You can pay with your credit card or by using PayPal. Once you have configured your payment information, DigitalOcean will ask you for some information about your project so that it can configure your Droplet faster:

In the next section, we will create our first Droplet.

Creating our first Droplet

We will create a new Droplet from scratch. Follow these steps to do so:

  1. Select the New Droplet option, as shown in the following screenshot:
  1. Choose Ubuntu 20.04 (LTS) x64, as follows:
  1. Then, choose the Basic plan, as shown here:
  1. You can then choose $5/mo in the payment plan options:
  1. Select a region. In this case, we will select the San Francisco region:
  1. Create a root password, add the name of your Droplet and then click on the Create Droplet button, as follows:
  1. It will take around 30 seconds to create your Droplet. Once it has been created, you will be able to see it:
  1. Now, in your Terminal, you can access the Droplet by using the following command:
ssh root@THE_DROPLET_IP
  1. The first time you access it will ask you for the fingerprint, you just need to write Yes, and then it will require your password (the one you defined when you created your droplet).

Now we are all set to install Node.js, which we will be covering in the next section.

Installing Node.js

Now that you're connected to your Droplet, let's configure it. First, we need to install the latest version of Node.js using a Personal Package Archive. The current version of Node at the time of writing this book is 14.16.x. Follow these given steps to install Node.js:

  1. If, when you are reading this paragraph, Node has a new version, change the version in the setup_14.x command:
cd ~
curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh
  1. Once you get the nodesource_setup.sh file, run the following command:
sudo bash nodesource_setup.sh
  1. Then, install Node by running the following command:
sudo apt install nodejs -y
  1. If everything works fine, verify the installed version of Node and npm with the following commands:
node -v
v14.16.1
npm -v
6.14.12

If you need a newer version of Node.js, you can always upgrade it.

Configuring Git and GitHub

I created a special repository for helping you to deploy your first React application to production (https://github.com/D3vEducation/production).

In your Droplet, you need to clone this Git repository (or your own repository if you have your React application ready to be deployed). The production repository is public, but normally you will use a private repository; in this case, you need to add the SSH key of your Droplet to your GitHub account. To create this key, follow these steps:

  1. Run the ssh-keygen command and then press Enter three times without writing any passphrase:
If you left your Terminal inactive for more than five minutes, your Droplet connection will probably be closed, and you will need to connect again.
  1. Once you have created your Droplet SSH key, you can see it by running the following command:
 vi /root/.ssh/id_rsa.pub

You will see something like this:

  1. Copy your SSH key and then visit your GitHub account. Go to Settings | SSH and GPG Keys (https://github.com/settings/ssh/new). Then, paste your key in the text area and add your title to the key:
  1. Once you click on the Add SSH key button, you will see your SSH key, like so:
  1. Now you can clone our repository (or yours) using the following command:
git clone [email protected]:FoggDev/production.git
  1. When you clone it for the first time, you will get a message asking you to allow the RSA key fingerprint:
  1. You have to write yes and then hit Enter to be able to clone it:
  1. Then, you have to go to the production directory and install the npm packages:
cd production
npm install
  1. If you want to test the application, just run the start script:
npm start
  1. Then open your browser and go to your Droplet IP and add the port number. In my case, it is http://144.126.222.17:3000:
  1. This will run the project in development mode. If you want to run in production mode, then use the following command:
npm run start:production

You should see PM2 running, as shown in the following screenshot:

  1. If you run it and you view the Network tab in your Chrome DevTools, you will see the bundles being loaded:

We now have our React application working in production, but let's see what else we can do with DigitalOcean in the next section.

Turning off our Droplet

To turn off the Droplet, follow these steps:

  1. If you want to turn off your Droplet, you can go to the Power section, or you can use the ON/OFF switch:
  1. DigitalOcean will charge you only when your Droplet is ON. If you click on the ON switch to turn it off, then you will get the following confirmation message:

In this way, you can control your Droplet and avoid paying unnecessarily when you're not using your Droplet.

Configuring nginx, PM2, and a domain

Our Droplet is ready to be used for production, but as you can see, we are still using port 3000. We need to configure nginx and implement a proxy to redirect the traffic from port 80 to 3000; this means we won't need to specify the port directly anymore. Node Production Process Manager (PM2) will help us run the Node server in production securely. Generally, if we run Node directly with the node or babel-node commands, and there is an error in the app, then it will crash and will stop working. PM2 restarts the node server if an error occurs.

First, in your Droplet, you need to install PM2 globally:

npm install -g pm2

PM2 will help us to run our React app in a very easy way.

Installing and configuring nginx

To install nginx, you need to execute the following command:

sudo apt-get update
sudo apt-get install nginx

After you have installed nginx, then you can start the configuration:

  1. We need to adjust the firewall to allow the traffic for port 80. To list the available application configurations, you need to run the following command:
sudo ufw app list
Available applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
  1. Nginx Full means that it will allow the traffic from port 80 (HTTP) and port 443 (HTTPS). We haven't configured any domain with SSL, so, for now, we should restrict the traffic to be sent just through port 80 (HTTP):
sudo ufw allow 'Nginx HTTP'
Rules updated
Rules updated (v6)

If you try to access the Droplet IP, you should see nginx working:

  1. You can manage the nginx process with these commands:
Start server: sudo systemctl start nginx
Stop server: sudo systemctl stop nginx
Restart server: sudo systemctl restart nginx

Nginx is an amazing web server that is getting very popular nowadays.

Setting up a reverse proxy server

As I mentioned previously, we need to set up a reverse proxy server to send the traffic from port 80 (HTTP) to port 3000 (React app). To do this, you need to open the following file:

sudo vi /etc/nginx/sites-available/default

The steps are as follows:

  1. In the location / block, you need to replace the code in the file with the following:
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
  1. Once you have saved the file, you can verify whether there is a syntax error in the nginx configuration with the following command:
sudo nginx -t
  1. If everything is fine, then you should see this:
  1. Finally, you need to restart the nginx server:
sudo systemctl restart nginx

Now, you should be able to access the React application without the port, as shown in the following screenshot:

We are almost done! In the next section, we are going to add a domain to our Droplet.

Adding a domain to our Droplet

Using an IP to access a website is not nice; we always need to use a domain to help users find our website easier. If you want to use a domain on your Droplet, you need to change the nameservers of your domain to point to the DigitalOcean DNS. I normally use GoDaddy to register my domains. To do so using GoDaddy, follow these steps:

  1. Go to https://dcc.godaddy.com/manage/YOURDOMAIN.COM/dns, and then go to the Nameservers section:
  1. Click on the Change button, select Custom, and then specify the DigitalOcean DNS:
  1. Normally, it takes between 15 and 30 minutes for the DNS changes to be reflected; for now, after you have updated your Nameservers, go to your Droplet dashboard, and then choose the Add a domain option:
  1. Then, write your domain name, select your Droplet, and click on the Add Domain button:
  1. Now, you have to create a new record for CNAME. Select the CNAME tab, and in the HOSTNAME write www; in the alias field write @; by default, the TTL is 43200. All of this is to enable access to your domain using the www prefix:

If you did everything correctly, you should be able to access your domain and see the React application working. As I said before, this process can take up to 30 minutes, but in some cases, it can take up to 24 hours depending on the DNS propagation speed:

Amazing, now you have officially deployed your first React application to production!

Implementing CircleCI for continuous integration

I've been using CircleCI for a while and I can tell you that it is one of the best CI solutions: it is free for personal use, giving you unlimited repositories and users; you have 1,000 build minutes per month, one container, and one concurrent job; if you need more, you can upgrade the plan with an initial price of $50 per month.

The first thing you need to do is sign up on the site using your GitHub account (or Bitbucket, if you prefer). If you choose to use GitHub, you need to authorize CircleCI in your account, as shown in the following screenshot:

In the next section, we are going to add our SSH key to CircleCI.

Adding an SSH key to CircleCI

Now that you have created your account, CircleCI needs a way to log in to your DigitalOcean Droplet to run the deploy script. Follow these steps to complete this task:

  1. Create a new SSH key inside your Droplet using the following command:
ssh-keygen -t rsa
# Then save the key as /root/.ssh/id_rsa_droplet with no password.
# After go to .ssh directory
cd /root/.ssh
  1. After that, let's add the key to our authorized_keys:
cat id_rsa_droplet.pub >> authorized_keys
  1. Now, you need to download the private key. To verify that you can log in with the new key, you need to copy it to your local machine, as follows:
# In your local machine do:
scp root@YOUR_DROPLET_IP:/root/.ssh/id_rsa_droplet ~/.ssh/
cd .ssh

ssh-add id_rsa_droplet
ssh -v root@YOUR_DROPLET_IP

If you did everything correctly, you should be able to log in to your Droplet without a password, and that means CircleCI can access our Droplet too:

  1. Copy the content of your id_rsa_droplet.pub key and then go to your repository settings (https://app.circleci.com/settings/project/github/YOUR_GITHUB_USER/YOUR_REPOSITORY):
  1. Go to SSH Keys, as follows:
  1. You can also access the URL https://app.circleci.com/settings/project/github/YOUR_GITHUB_USER/YOUR_REPOSITORY/shh, and then click on the Add SSH Key button at the bottom:
  1. Paste your private key, and then provide a name for the Hostname field; we will name it DigitalOcean.

Now let's configure our CircleCI instance in the next section.

Configuring CircleCI

Now that you have configured access for CircleCI to your Droplet, you need to add a config file to your project to specify the jobs you want to execute for the deployment process. This process is shown in the following steps:

  1. For this, you need to create the .circleci directory and add the following inside the config.yml file:
version: 2.1
jobs:
build:
working_directory: ~/tmp
docker:
- image: cimg/node:14.16.1
steps:
- checkout
- run: npm install
- run: npm run lint
- run: npm test
- run: ssh -o StrictHostKeyChecking=no $DROPLET_USER@$DROPLET_IP 'cd production; git checkout master; git pull; npm install; npm run start:production;'
workflows:
build-deploy:
jobs:
- build:
filters:
branches:
only: master
  1. When you have a .yml file, you need to be careful with the indentation; it is similar to Python in that if you don't use indents correctly, you will get an error. Let's see how this file is structured.
  2. Specify the CircleCI version we will use. In this instance, you are using version 2.1 (the latest one at the time of writing this book):
version: 2.1
  1. Inside jobs, we will specify that it needs to configure the container; we will create it using Docker, and also outline the steps to follow for the deployment process.
  1. The working_directory will be the temporal directory we will use to install the npm packages and run our deploy scripts. In this case, I decided to use the tmp directory, as follows:
jobs:
build:
working_directory
: ~/tmp
  1. As I said before, we will create a Docker container, and in this instance, I selected an existing image that includes node: 14.16.1. If you want to know about all the available images, you can visit https://circleci.com/docs/2.0/circleci-images:
docker:
- image: cimg/node:14.16.1
  1. For the code case, first do a git checkout to master, then on each run sentence, you need to specify the scripts you want to run:
steps:
- checkout
- run: npm install
- run: npm run lint
- run: npm test
- run: ssh -o StrictHostKeyChecking=no $DROPLET_USER@$DROPLET_IP 'cd production; git checkout master; git pull; npm install; npm run start:production;'

Follow these steps:

  1. First, you need to install the npm packages using npm install to be able to perform the next tasks.
  2. Execute the ESLint validation using npm run lint. If it fails, it will break the deployment process, otherwise, it continues with the next run.
  3. Execute the Jest validations using npm run test; if it fails, it will break the deployment process, otherwise, it continues with the next run.
  4. In the last step, we connect to our DigitalOcean Droplet, passing the StrictHostKeyChecking=no flag to disable the strict host key checking. We then use the $DROPLET_USER and $DROPLET_IP ENV variables to connect to it (we will create those in the next step), and finally, we will specify all the commands we will perform inside our Droplet using single quotes. These commands are listed as follows:

cd production: Grants access to the production (or your Git repository name).

git checkout master: This will check out the master branch.

git pull: Pulls the latest changes from our repository.

npm run start:production: This is the final step, which runs our project in production mode.

Finally, let's add some environment variables to our CircleCI.

Creating ENV variables in CircleCI

As you saw previously, we are using the $DROPLET_USER and $DROPLET_IP variables, but how do we define those? Follow these steps:

  1. You need to go to your project settings again and select the Environment Variables option. Then, you need to create the DROPLET_USER variable:
  1. Then, you need to create the DROPLET_IP variable using your Droplet IP:
  1. Now, you need to push the config file to your repository, and you will be ready for the magic. Now that CircleCI is connected to your repository, every time you push changes to master, it will fire a build.

Normally, the first two or three builds can fail due to syntax errors, indent errors in our config, or maybe because we have linter errors or unit test errors. If you have a failure, you will see something like this:

  1. As you can see from the preceding screenshot, the first build failures at the bottom say Build Error, and the second one says workflow build-deploy. This basically means that in the first build I had a syntax error in the config.yml file.
  2. After you fix all the syntax errors in the config.yml file and all the issues with the linter or the unit tests, you should see a SUCCESS build, like this:
  1. If you click on the build number, you can see all the steps that CircleCI executed before publishing the new changes in your Droplet:
  1. As you can see, the order of the steps is the same as we specified in our config.yml file; you can even see the output of each step by clicking on it:
  1. Now, let's suppose you have an error on your linter validation or in some unit tests. Let's see what happen in that case, as follows:

As you can see, once an error is detected, it will exit with code 1. This means it will abort the deployment and will mark it as a failure, and as you can see, none of the steps after npm run lint are executed.

Another cool thing is that if you now go to your GitHub repository and check your commits, you will see all the commits that had a successful build and all the commits that had a failed build:

This is amazing – now you have your project configured to do deployments automatically and it is connected to your GitHub repository.

Summary

Our journey through the deployment process has come to an end, and now you know how to deploy your React application to the world (production), and also how to implement CircleCI for continuous integration.

In the next chapter, we will learn how to publish npm packages.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.236.139.73