Baeldung Pro – Ops – NPI EA (cat = Baeldung on Ops)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

Partner – Orkes – NPI EA (cat=Kubernetes)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

1. Introduction

Deploying React applications to a production-ready environment often requires efficiently and securely serving static files. Apache Tomcat, a widely used Java-based web server, is an excellent choice for hosting React applications due to its robust configuration options and high reliability.

In this tutorial, we’ll explore the detailed process of building and deploying a React application on a Tomcat server. This involves creating a React application, enhancing it with routing, and configuring the Tomcat server. At the end of this tutorial, we’ll have a React application running seamlessly on the Tomcat server.

We tested all the commands and code in this tutorial on Kali Linux. Unless otherwise specified, it should work in most Linux environments

2. Building a Simple React Application

To illustrate the deployment process, we create a sample React application and prepare it for deployment. Additionally, we also include routing functionality to simulate a real-world application scenario.

2.1. Creating a New React Application

Firstly, we use the create-react-app CLI tool to scaffold a new React project:

$ npx create-react-app my-sample-app

The command creates a new directory named my-sample-app with all the necessary files and dependencies for a React application.

2.2. Installing React Router DOM for Routing

Next, let’s start with adding routing functionality to the application. We install the react-router-dom library which is essential for managing navigation in React applications:

$ cd my-sample-app
$ npm install react-router-dom

This library allows us to define and manage routes seamlessly.

2.3. Updating the React Application

Furthermore, we now update the src/App.js file to include routing logic. This file defines the main application component, which serves as the application entry point. Let’s replace the existing content of src/App.js with a new implementation:

cat > src/App.js << EOF
import React from "react";
import { BrowserRouter as Router, Route, Routes, Link } from "react-router-dom";

const Home = () => <h2>Welcome to My Sample React App!</h2>;
const About = () => <h2>About This App</h2>;

function App() {
    return (
        <Router>
            <div>
                <nav>
                    <ul>
                        <li><Link to="/">Home</Link></li>
                        <li><Link to="/about">About</Link></li>
                    </ul>
                </nav>
                <Routes>
                    <Route path="/about" element={<About />} />
                    <Route path="/" element={<Home />} />
                </Routes>
            </div>
        </Router>
    );
}

export default App;
EOF

This updated file introduces two pages which are Home and About. Additionally, it defines the navigation links for routing between them.

Further, let’s adjust the base URL (Homepage) in the package.json file on the React application:

$ nano package.json
...
  },
  "homepage": "http://localhost:8080/simpleapp"
}

Here, we added the “homepage”: “http://localhost:8080/simpleapp to the JSON file. It ensures the generated build file references the correct base path for assets.

2.4. Building the React Application

Finally, let’s build the React application in the React project directory and generate the production build:

$ npm run build

The build artifacts are generated in the build directory. Additionally, this directory contains static files, such as index.html, JavaScript bundles, and CSS, ready to be served by a web server like Tomcat.

3. Installing and Setting Up Apache Tomcat Server

With the React application built and ready, let’s prepared to move on to setting up Apache Tomcat and deploying the application.

3.1. Downloading and Installing Apache Tomcat

Apache Tomcat is available as a compressed archive that can be downloaded directly from its official website. As of the time of writing this article, the latest version of Apache Tomcat is version 11.0.1.

Firstly, let’s download the Tomcat archive using wget the command:

$ wget https://downloads.apache.org/tomcat/tomcat-11/v11.0.1/bin/apache-tomcat-11.0.1.tar.gz
...

apache-tomcat-11.0.1.tar.gz  100%[==============================================>]  13.01M   830KB/s    in 14s

2024-12-06 08:55:35 (976 KB/s) - ‘apache-tomcat-11.0.1.tar.gz’ saved [13643429/13643429]

Once downloaded, we extract the content of the archive:

$ tar -xvzf apache-tomcat-11.0.1.tar.gz

Note that the extracted directory contains all the files necessary for running Tomcat.

3.2. Setting Up a Dedicated Tomcat User

For better security and management, let’s create a dedicated system user for running the Tomcat service:

$ sudo useradd -r -m -U -d /opt/tomcat -s /bin/false tomcat

Let’s explain what each of them does:

  • -r: creates a system account
  • -m: creates the home directory for the user
  • -U: creates a group with the same name as the user
  • -d: specifies the home directory service for the user
  • -s /bin/false: disable shell access for the user

Additionally, this user will not have login privileges.

Next, let’s move the extracted Tomcat files to the appropriate directory under /opt:

$ sudo mv apache-tomcat-11.0.1 /opt/tomcat

For easier management, we create a symbolic link to the Tomcat directory:

$ sudo ln -s /opt/tomcat/apache-tomcat-11.0.1 /opt/tomcat/updated

In particular, this link ensures that future upgrades can be managed without modifying existing configurations.

Further, let’s change the ownership of the Tomcat files to the dedicated tomcat user:

$ sudo chown -R tomcat: /opt/tomcat/*

Additionally, we grant permissions for the Tomcat scripts located in the bin directory:

$ sudo sh -c 'chmod +x /opt/tomcat/updated/bin/*.sh'

This step ensures all startup and management scripts are executable.

3.3. Configuring Tomcat as a Service

Furthermore, let’s create a systemd service file for Tomcat:

$ sudo nano /etc/systemd/system/tomcat.service

Then, we add the following configuration inside the file:

[Unit]
Description=Apache Tomcat Web Application Container
After=network.target

[Service]
Type=forking

Environment="JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64"
Environment="CATALINA_PID=/opt/tomcat/updated/temp/tomcat.pid"
Environment="CATALINA_HOME=/opt/tomcat/updated/"
Environment="CATALINA_BASE=/opt/tomcat/updated/"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
Environment="JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom"

ExecStart=/opt/tomcat/updated/bin/startup.sh
ExecStop=/opt/tomcat/updated/bin/shutdown.sh

User=tomcat
Group=tomcat
UMask=0007
RestartSec=10
Restart=always

[Install]
WantedBy=multi-user.target

Next, we reload the systemd daemon to apply the changes:

$ sudo systemctl daemon-reload

Furthermore, we start the Tomcat service:

$ sudo systemctl start tomcat

To check if it’s successful, let’s verify the status of the Tomcat service:

$ sudo systemctl status tomcat
● tomcat.service - Apache Tomcat Web Application Container
     Loaded: loaded (/etc/systemd/system/tomcat.service; disabled; preset: disabled)
     Active: active (running) since Fri 2024-12-06 16:33:00 EST; 32s ago
    Process: 103015 ExecStart=/opt/tomcat/updated/bin/startup.sh (code=exited, status=0/SUCCESS)
   Main PID: 103022 (java)
      Tasks: 31 (limit: 4615)
     Memory: 167.9M
        CPU: 4.695s
     CGroup: /system.slice/tomcat.service
             └─103022 /usr/lib/jvm/java-1.17.0-openjdk-amd64/bin/java -Djava.util.logging.config.file=/opt/tomcat/u>

Dec 06 16:33:00 kali systemd[1]: Starting Apache Tomcat Web Application Container...
Dec 06 16:33:00 kali startup.sh[103015]: Tomcat started.
Dec 06 16:33:00 kali systemd[1]: Started Apache Tomcat Web Application Container.

Finally, we enable the Tomcat service to start on boot:

$ sudo systemctl enable tomcat
Created symlink /etc/systemd/system/multi-user.target.wants/tomcat.service → /etc/systemd/system/tomcat.service.

We now have Apache Tomcat installed and running as a system service, ready for deploying the React applications.

4. Deploying React Application to Tomcat Server

Deploying the react application to the Tomcat server is seamless. Since we’ve built the react application in the earlier section, we copy the build folder to the Tomcat webapps directory:

$ sudo cp -r /home/kali/my-sample-app/build /opt/tomcat/updated/webapps/simpleapp

Here, the simpleapp directory name matches the basename used in the React application’s Router. Furthermore, once the React application’s build files are in place, Tomcat will automatically deploy the application.

Additionally, we can verify the deployment by navigating to the following URL:

http://ip-address:8080/simpleapp

We replace ip-address with our system IP address.

Successful Deployment of React Application

As can be seen, the deployment of the react application on the Apache Tomcat server has been successful.

5. Conclusion

In this article, we’ve demonstrated the process of deploying a React application on an Apache Tomcat server. We started with building a sample react application and incorporating routing functionalities to configure and secure the Tomcat environment.

Furthermore, this approach highlights the compatibility of modern web frameworks with traditional server technologies like Tomcat.

The code for the entire application alongside the server is available over on GitHub.