Running React and Node.js in one shot with Docker!

3 min read

This is the second part of my previous post. If you haven't read my first post, please check it out as it serves as a base for this part.

TL;DR - If you don't know docker you can just turn back. But, If you still want to read go ahead.

In this post we'll be looking at the docker way of running React and Node.js. This is a kind of advance development setup and I hope you already installed (opens in a new tab) and know the basics of docker (opens in a new tab) and docker-compose (opens in a new tab). If you want to know more about docker head over to docker.com (opens in a new tab)

# Initial setup

$ mkdir awesome_project

In this approach we'll not polluting the root folder. Client and Server will stay on their dedicated folder. In this way we can separate client and server at any time if we have to, without breaking anything. To make it work properly, each of them should have a Dockerfile (opens in a new tab) and all will be connected with the docker-compose.

# Client Setup (React)

~ Create react app

$ cd awesome_project && npx create-react-app client

This will create a folder named client which holds our react app.

~ Dockerfile for React

Create a file name Dockerfile in the client folder and paste the following code.

FROM node:lts-slim
 
RUN mkdir -p /usr/src/app
 
WORKDIR /usr/src/app
 
EXPOSE 3000
 
CMD [ "npm", "start" ]

This will be our docker image instructions for our react app where our react app will get compiled and run.

# Server Setup (Node.js)

Our server code will stay in a folder named server in the root folder. Here you can use express or any other framework of your choice to make up the server. Or you can use this sample (opens in a new tab) to quickly setup a server.

~ Dockerfile for Node Server

Create a Dockerfile in the server folder. And make sure you have a dev script in you package.json. If you have different script for running your server, you can change the CMD instruction in the Dockerfile below.

FROM node:lts-slim
 
RUN mkdir -p /usr/src/app
 
WORKDIR /usr/src/app
 
EXPOSE 5000
 
# You can change this
CMD [ "npm", "run", "dev" ]

# Running with docker-compose

Docker-compose helps us to combine and run mutiple Dockerfile into a single network container. Make a file named docker-compose.yml in the root of the project and copy the following code.

version: "3"
services:
    frontend:
        container_name: awesome_web
        build:
            context: ./client
            dockerfile: Dockerfile
        image: vikasraj/awesome_web
        ports:
            - "3000:3000"
        volumes:
            - ./client:/usr/src/app
    backend:
        container_name: awesome_server
        build:
            context: ./server
            dockerfile: Dockerfile
        image: vikasraj/awesome_server
        ports:
            - "5000:5000"
        volumes:
            - ./server:/usr/src/app

Finally, we'll have a folder structure somewhat like this.

> awesome_project
    > client # This is our react front-end
        > node_modules
        > src
        - Dockerfile
        - package.json
    > server # This is our Node.js server
        > node_modules
        - index.js
        - Dockerfile
        - package.json
    - docker-compose.yml

Now we can run our project by running following command. This will create docker images and volumes (opens in a new tab) which will run in the containers.

$ docker-compose up

If you want to build your images before starting your containers.

$ docker-compose up --build

This can be a tedious approach to work with as you must have the knowledge of docker and docker-compose. But It has some advantage: