Deploying a React App to AWS Elastic Beanstalk

Learn how to deploy a React application to AWS Elastic Beanstalk with the Elastic Beanstalk CLI and GitHub Actions.

Have you been looking for a way to deploy React applications to AWS Elastic Beanstalk? If so, then this tutorial is for you. In this tutorial, you will crisply build a React application, dockerize it, and deploy it to AWS Elastic Beanstalk. You will also learn how to automate the deployment with GitHub actions on every code change.

The complete application can be found on GitHub.

Prerequisites

If you’d like to follow along, you should have the following:

Building a React Application

To illustrate the process of deploying a React app to AWS Elastic Beanstalk, we will quickly build an application with React. This application will simply fetch some dog-related data from an API and display it on a web browser.

On your home directory, run the following command to create a React app called dog-app.

mkdir react-ebn #creates a working directory
npx create-react-app dog-app #creates the react app
cd dog-app #Go into the react app
code . #Open up the react project with your preferred code editor

Create a components folder and a styles folder. In the components folder, create a file named Dogs.jsx and paste the following code.

This code defines a React component that fetches and displays a random dog image from a public API. The component uses useEffect and useState hooks to manage states and perform side-effects. The component displays a loading message while the image is being fetched, as well as a button to fetch a new image after the image loads.

import { useEffect, useState } from "react";
import '../styles/dogs.css'

const Dogs = () => {
    const loadDogs = () => {
        setLoading(true)
       fetch("https://dog.ceo/api/breeds/image/random")
            .then((res) => res.json())
            .then((data) => {
                setDog(data.message)
                setLoading(false)
            }); 
    }
    const [dog,setDog] = useState([]);
    const [loading, setLoading] = useState(true);
    useEffect(() => {loadDogs()}, []);

    if(loading) {
       return <h1>Getting dog...</h1>
    }

    return (   
        <div>
            <div className="dog-app-container">
                <h2>Get random dog images</h2>
                <div className="image-container">
                    <img src={dog} alt="Dog"/>
                </div>
                <button onClick={loadDogs}>Fetch dog! </button>
            </div>
        </div>
    );

}

export default Dogs;

In the styles folder, create a dogs.css file and paste the following code snippets. This will perform some basic styling for the homepage.

@import url('https://fonts.googleapis.com/css2?family=Comfortaa:wght@500&display=swap');

h1{
    text-align: center;
    font-family: 'Comfortaa', cursive; 
}

h2{
    font-family: 'Comfortaa', cursive; 
}

.dog-app-container{
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    margin: 50px;
}

.image-container {
    width: 350px;
    height: 350px;
    border: 3px solid rgb(128, 106, 106);
    border-radius: 5px;
}

img{
    width: 100%;
    height: 100%;
    display: block;
}

button{
    margin: 20px;
    padding: 10px;
    background-color: hsl(244, 80%, 60%);
    border: none;
    color: white;
    cursor: pointer;
    font-family: 'Comfortaa', cursive;
}

button:hover{
    filter: brightness(90%);
}

Now, add the code snippets below to the App.js file to utilize the Dogs component we created earlier:

import Dogs from './components/Dogs'
import './App.css';

function App() {
  return <Dogs/>
}

export default App;

Finally, remove the margin property in the index.css file, leaving you with the following *CSS* styles:

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

Open a terminal window and run the following command to open the React application in your favorite web browser. You should see the following output running on localhost:3000.

npm start

Image of React application Dog app on the browser

Dockerizing the React Application

Elastic Beanstalk requires your application to be dockerized before deploying it. On the root of the dog-app directory, create a Dockerfile and add the following configuration settings.

The configuration settings in the Dockerfile is what Elastic Beanstalk will use to build the image to deploy the React application.

FROM node:17.1-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:1.22.1-alpine as prod-stage
COPY --from=build-stage /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Run the Docker commands below to confirm the React application is running as intended on your host machine:

docker build -t react-ebn  .
docker run --name react-ebn_c -p 8080:80 react-ebn

If you have the React application running on localhost:8080, then you are ready to proceed with Elastic Beanstalk.

Now, push the React application (Dog-app) to your Git repository using the commands below. This step is essential, as Elastic Beanstalk uses the Git archive of the most recent commit. Since you don’t have Git initialized in the React project, Elastic Beanstalk will have nothing to deploy with and will incur errors.

git init #Initialize git project
git add . #adds changes to staging area
git commit -m 'first-commit' #commits your changes
git remote add origin git@github.com:github_username/react-elastic-beanstalk.git #Your own repository goes here
git push -u origin master #Push to GitHub repository master branch

Setting Up Elastic Beanstalk CLI for the React Application

At this point, you have created a React app and built a Docker container for it that is accessible on your machine. Now, you will deploy the React application to Elastic Beanstalk using the Elastic Beanstalk(EB) CLI.

First, you’ll need to set up the AWS Elastic Beanstalk environment for your project in your working directory dog-app by running the following command:

eb init

The EB CLI will prompt you to select a region. Select the default region by pressing Enter.

Next, it will prompt you to give the application a name; this tutorial uses an application name react-app.

Then, it will ask you to confirm the platform you are currently working with, which is Docker; press enter to continue.

Selecting platform Docker

Now press Enter to use the default platform branch. Hit (n) to disable CodeComit, and hit (n) so the EB CLI won’t set up ssh for your instances.

Selecting the default platform branch and disabling codeCommit

Create an environment for the React application by executing the following command:

You’ll need to do this so that EB CLI can deploy your application.

eb create

The command above will prompt you to provide values for the Environment name, DNS CNAME, and LoadBalancer type of the environment. You will select their defaults, hit (n) to disallow EB CLI from enabling Spot Fleet requests for your environment, and proceed to creating your application environment.

If your development was created successfully, you should have the following output:

verifying successful creation of development environment

Now, to access your application, run the following EB command:

eb open

Next, by default, Elastic Beanstalk stores your application in a storage bucket (Amazon s3). Therefore, to see your application, search s3 on the navigation menu and select s3 as shown below:

Selecting Amazon s3

You should see a screen containing your application, its region, and the date it was created.

Finally, if you click on it, you will see all the other details for your application and its resources.

Automate Deployment to Elastic Beanstalk with GitHub Actions

GitHub Actions is a platform that allows you to perform CI/CD operations. Thus, other than the EB CLI, you can use GitHub Actions to create workflows to test, build and deploy your application to Elastic Beanstalk based on every commit on your GitHub repository. You can also set instructions to perform other checks with GitHub actions.

In your Dog-app directory, create a .github/workflows directory. This will contain your workflow files.

Next, create a file called eb.yaml and add these configuration settings:

name: Deploy React App from GitHub to AWS Elastic Beanstalk
on:
  # activates the workflow when there is a push on the master branch
  push:
    branches:
      - master
jobs:
  deploy:
    runs-on: ubuntu-latest # the operating system your job should run on
    strategy:
      matrix:
        node-version: [17.x]
    steps:
      - name: Checkout Latest Repo
        # checks out your repository under the GitHub workspace so that your workflow can access it
        uses: actions/checkout@v2

      - name: Generate Deployment Package 
        # zip all files except .git
        run: zip -r deploy-dog-app.zip * -x "**.git**"

      - name: Get timestamp
        uses: gerred/actions/current-time@master
        id: current-time

      - name: Run string replace
        uses: frabert/replace-string-action@master
        id: format-time
        with:
          # replaces '[:\.]+' in the timestamp with '-'
          pattern: '[:\.]+'
          string: "${{ steps.current-time.outputs.time }}"
          replace-with: '-'
          flags: 'g'

      - name: Deploy to EB
        uses: einaregilsson/beanstalk-deploy@v21
        with:
         #  input the credentials you used to setup AWS CLI and credentials for the application environment
          aws_access_key: "${{ secrets.ACCESS_KEY }}"
          aws_secret_key: "${{ secrets.SECRET_ACCESS_KEY }}"
          application_name: react-app
          environment_name: react-app-dev
          version_label: "app-${{ steps.format-time.outputs.replaced }}"
          region: us-west-2
          deployment_package: deploy-dog-app.zip

      - name: Deployed!
        run: echo App deployed to ELB

There are a few things to note while deploying any application to AWS Elastic Beanstalk with GitHub Actions:

Now head over to your GitHub repository and add the ACCESS_KEY and SECRET_ACCESS_KEY for the IAM user as secrets in your repository.

Adding ACCESS_KEY and SECRET_ACCESS_KEY as action secrets on GitHub repository

Run the following commands to push your commits to trigger the GitHub workflow:

git add .
git commit -m 'Added GitHub workflow'
git push origin master

Head over to your Git repository, and then click on the “Actions” tab to see the status of your workflow. The yellow rolling icon beside the workflow run indicates that your workflow is in progress.

You’ll need to wait awhile for your workflow to complete its run successfully.

To check other details about your workflow and the jobs that succeeded, click on the workflow run, and you should see a list of jobs in the same order it was defined in your workflow file.

Run the command below to open up your deployed application:

eb open

You should see your React application (Dog-app) opened in your browser as shown below:

Viewing Dog-app application deployed with GitHub actions in the browser

At this point, as you develop the React application and commit the changes to your GitHub repository, a new workflow is run, and your application is deployed automatically to AWS Elastic Beanstalk.

Conclusion

In this article, you have learned how to deploy a React (Dog-app) application to AWS Elastic Beanstalk. You have also learned how to use GitHub Actions to develop a workflow that automatically deploys every commit made on the Git repository housing your application to Elastic Beanstalk.

You can take this a step further by adding more steps to your GitHub Actions pipeline, such as testing and other checks.

What to do next:
  1. Try Honeybadger for FREE
    Honeybadger helps you find and fix errors before your users can even report them. Get set up in minutes and check monitoring off your to-do list.
    Start free trial
    Easy 5-minute setup — No credit card required
  2. Get the Honeybadger newsletter
    Each month we share news, best practices, and stories from the DevOps & monitoring community—exclusively for developers like you.
    author photo

    Muhammed Ali

    Muhammed is a Software Developer with a passion for technical writing and open source contribution. His areas of expertise are full-stack web development and DevOps.

    More articles by Muhammed Ali
    Stop wasting time manually checking logs for errors!

    Try the only application health monitoring tool that allows you to track application errors, uptime, and cron jobs in one simple platform.

    • Know when critical errors occur, and which customers are affected.
    • Respond instantly when your systems go down.
    • Improve the health of your systems over time.
    • Fix problems before your customers can report them!

    As developers ourselves, we hated wasting time tracking down errors—so we built the system we always wanted.

    Honeybadger tracks everything you need and nothing you don't, creating one simple solution to keep your application running and error free so you can do what you do best—release new code. Try it free and see for yourself.

    Start free trial
    Simple 5-minute setup — No credit card required

    Learn more

    "We've looked at a lot of error management systems. Honeybadger is head and shoulders above the rest and somehow gets better with every new release."
    — Michael Smith, Cofounder & CTO of YvesBlue

    Honeybadger is trusted by top companies like:

    “Everyone is in love with Honeybadger ... the UI is spot on.”
    Molly Struve, Sr. Site Reliability Engineer, Netflix
    Start free trial
    Are you using Sentry, Rollbar, Bugsnag, or Airbrake for your monitoring? Honeybadger includes error tracking with a whole suite of amazing monitoring tools — all for probably less than you're paying now. Discover why so many companies are switching to Honeybadger here.
    Start free trial
    Stop digging through chat logs to find the bug-fix someone mentioned last month. Honeybadger's built-in issue tracker keeps discussion central to each error, so that if it pops up again you'll be able to pick up right where you left off.
    Start free trial
    “Wow — Customers are blown away that I email them so quickly after an error.”
    Chris Patton, Founder of Punchpass.com
    Start free trial