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
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
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;
Run the frontend to make sure you have it fully functioning:
npm start
You should see the following on http://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"]
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
Make sure to install the following packages first:
npm install express
npm install cors
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')
})
Run the backend:
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:
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:
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"]
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
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
And open http://localhost:3000
to see the same frontend UI up and the backend sending its response:
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
In myApp/backend/
, run
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.