DEV Community

Cover image for React-Node Docker Example with Docker Compose
Faris Durrani
Faris Durrani

Posted on

React-Node Docker Example with Docker Compose

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.



mkdir myApp


Enter fullscreen mode Exit fullscreen mode

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

We’ll use a simple create-react-app command as detailed here to create a React frontend inside myApp/.



npx create-react-app frontend  
cd frontend


Enter fullscreen mode Exit fullscreen mode

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



// 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;


Enter fullscreen mode Exit fullscreen mode

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



npm start


Enter fullscreen mode Exit fullscreen mode

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

Screenshot - React app default start page on localhost 3000

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



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


Enter fullscreen mode Exit fullscreen mode

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:



mkdir backend  
cd backend  
npm init -y


Enter fullscreen mode Exit fullscreen mode

Make sure to install the following packages first:



npm install express  
npm install cors


Enter fullscreen mode Exit fullscreen mode

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



// 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')
})


Enter fullscreen mode Exit fullscreen mode

Run the backend:



node index.js


Enter fullscreen mode Exit fullscreen mode

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

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

Create a Dockerfile for the backend:



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


Enter fullscreen mode Exit fullscreen mode

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:



# 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


Enter fullscreen mode Exit fullscreen mode

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):



docker compose up


Enter fullscreen mode Exit fullscreen mode

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

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



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


Enter fullscreen mode Exit fullscreen mode

In myApp/backend/, run



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


Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)