React-Node Docker Example with Docker Compose
Tags: react, docker, node
Published: 2023-06-06 01:48:48

*A simple Node backend-React frontend app deployed on Docker living on localhost ports 3000 and 4000*

React is an open-source JavaScript library primarily used for building user interfaces (UIs) for web applications, which constitute the frontend. The backend, built using NodeJS for example, is the interface that services the users’ more complex requests such as saving to the database.

When you're ready to deploy your app to a production environment or share it with others, it's important to have a consistent environment with the correct operating system and necessary packages. That's where Docker comes in - it automates the process of deploying and managing applications in lightweight, separate containers. This guide will show you how to deploy a React frontend coupled with a NodeJS backend in Docker and Docker Compose.

## Prerequisites

This guide has the following installed. Since what we’re doing is pretty basic, the versions don’t matter as much:

- NodeJS v18 (with NPM v9)
- Docker v23 (with Docker Compose)

## Step 1: Create a directory

Create a directory where you want to store the frontend and backend.

```sh
mkdir myApp
```

## Step 2: Create the frontend (in `myApp/frontend`)

We’ll use a simple create-react-app command as detailed [here](https://create-react-app.dev/docs/getting-started/) to create a React frontend inside `myApp/`.

```sh
npx create-react-app frontend  
cd frontend
```

Let’s change `frontend/src/App.js` to the following so it fetches data from the backend:

```js
// frontend/src/App.js
import logo from "./logo.svg";
import "./App.css";
import React, { useEffect } from "react";

function App() {
  const fetchData = async () => {
    const res = await fetch("http://localhost:4000/");
    console.log(res);
  };

  useEffect(() => {
    fetchData();
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
```

Run the frontend to make sure you have it fully functioning:

```sh
npm start
```

You should see the following on `http://localhost:3000`:


![Screenshot - React app default start page on localhost 3000](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ln4t4shtjr64aq3hu2uo.png)

Also, let’s create the Dockerfile for the frontend where Docker will use to create the Docker image for the frontend:

```Dockerfile
# frontend/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
```

## Step 3: Create the backend (in `myApp/backend/`)

At the root directory `/myApp` , let’s create the backend. Run this command to change the directory to the backend and initiate the basic NodeJS files:

```sh
mkdir backend  
cd backend  
npm init -y
```

Make sure to install the following packages first:

```sh
npm install express  
npm install cors
```

Create an `index.js` file in the same directory, which houses the actual backend function:

```js
// backend/index.js
const express = require('express')
const cors = require('cors')

const app = express()

app.use(cors())

app.get('/', (req, res) => {
  res.json([
    {
      "id":"1",
      "title":"Book Review: The Name of the Wind"
    },
    {
      "id":"2",
      "title":"Game Review: Pokemon Brillian Diamond"
    },
    {
      "id":"3",
      "title":"Show Review: Alice in Borderland"
    }
  ])
})

app.listen(4000, () => {
  console.log('listening for requests on port 4000')
})
```

Run the backend:

```sh
node index.js
```

And you should see the following if you go to `http://localhost:4000` which verifies the backend is sending the JSON item:

![Screenshot - localhost 4000 showing JSON response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zfrieq44i4u2grawvi92.png)

With the frontend also running, refresh `http://localhost:3000` and open the console log (Cmd/Ctrl + Shift + C on Google Chrome). You should see the backend’s JSON response printed:

![Screenshot - localhost 3000 with JSON response in console from port 4000](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bytlbakgsqbwf9fvfjbu.png)

Create a Dockerfile for the backend:

```Dockerfile
# backend/Dockerfile
FROM node:18-alpine
WORKDIR '/app'
COPY package.json .
RUN npm install
COPY . .
EXPOSE 4000
CMD ["node", "index.js"]
```

## Step 4: Create Docker Compose (in `myApp/` )

Of course, you could just run both the frontend and backend Docker containers manually but Docker Compose just gives a more standardized way of doing it. In `myApp/` , create a `docker-compose.yaml` file:

```yaml
# myApp/docker-compose.yaml
version: "3.8"
services:
  frontend:
    build: ./frontend
    container_name: frontend_c
    ports:
      - '3000:3000'
  backend:
    build: ./backend
    container_name: backend_c
    ports:
      - '4000:4000'
    stdin_open: true
    tty: true
```

Run the `docker-compose.yaml` file by running (you should stop the frontend and backend instances that you started before if you haven’t already):

```sh
docker compose up
```

And open `http://localhost:3000` to see the same frontend UI up and the backend sending its response:

![Screenshot - localhost 3000 with JSON response in console from port 4000](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bytlbakgsqbwf9fvfjbu.png)

And now you have your React frontend-backend app running using Docker Compose!

## Bonus: How to run the frontend and backend containers separately without Docker Compose

If you don’t want to use Docker Compose, you can always run the frontend and backend containers separately using their respective Dockerfiles.

In `myApp/frontend/`, run

```sh
docker build -t frontend_container .
docker run -p 3000:3000 frontend_container
```

In `myApp/backend/`, run

```sh
docker build -t backend_container .
docker run -p 4000:4000 backend_container
```

The `-p 3000:3000` means Docker is forwarding whatever it receives in the container’s port 3000 to your computer’s localhost’s port 3000.

***Safe harbor statement***
The information provided on this channel/article/story is solely intended for informational purposes and cannot be used as a part of any contractual agreement. The content does not guarantee the delivery of any material, code, or functionality, and should not be the sole basis for making purchasing decisions. The postings on this site are my own and do not necessarily reflect the views or work of Oracle or Mythics, LLC.

*This work is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/).*