The original article with code samples and images is available here ->
If you have been through my Blog before, you’ll probably know I’m a big fan of React. What I wasn’t a big fan of earlier was Docker, guess why? Because I did not know anything about Docker. Over the last few months I’ve had a chance to work with and study about Docker and to be honest, there’s everything to love about it. In this article, we’ll see how we can serve a React application using Nginx and Docker with the help of docker-compose. We’ll take a look at all these four things briefly but our main focus would be on how to make all of them work together.
Also, it is not important for you to serve a React application as such, you can actually serve ANY application – be it an Express app, a Ruby on Rails app or just about anything running on a port. For this article though, let’s keep ourselves to React.
Setting up the React application
If you have an already created React application, that’s well and good, you can basically skip this entire section then.
If not, let us quickly use create-react-app to hack up a React application for us. I’m assuming you do have Node and npm installed on your system to set up this application (even though you won’t ACTUALLY be needing it with Docker later). If not, a simple google search on how to install them would bring you more results than I can begin to explain..
Using npx to create a react application
Here’s a quick anecdote for some of you who don’t know it –
npx stands for Node Package Execute and it does not require you to install a package before being able to use it on your machine. It directly executes the package from the npm registry itself.
Also, npx only gets installed with npm v5.2 and above
Just running these three small commands should get your React application up and running. If you know React and would like to make changes to your application – go ahead.
In this article though, we’ll be using the blueprint created React app itself.
Dockerizing the React application
The next step for us is to dockerize our React application. If you do not know what Docker is please check this article out – Docker for absolute beginners.
To dockerize our React app, we must create two files inside our React app directory, namely – Dockerfile and .dockerignore .
Dockerfile is the file that contains all the configuration for us to create a docker image and then run that image as a container.
.dockerignore is a file just like .gitignore and to be honest, I just copy and paste the contents from .gitignore to my .dockerignore like 99% of the times.
Oh, and also – Please install Docker on your system in case you don’t have it. None of it will work without it 😛
Dockerfile for our react application
Let us go through this Dockerfile a bit :-
FROM – A command that chooses the base image for your React application. As React works on Node, it is good to have any base Node image. We chose alpine here as it is the smallest in size.
WORKDIR – The working directory inside your docker container where all the application code will live in. It is a good practice to not have the application code in the root of the docker container so we chose /node/app.
COPY – We copy the package.json file from our current directory (ie, root of the React application) and paste it into the /node/app directory (where our react code will live inside the docker container).
RUN – We want to run npm install after we have copied the package.json file in the docker container.
COPY – Copying all the other files in the directory into the React directory in the docker container.
EXPOSE – The port we want to expose from our docker container to the host machine. 3000 because that is what our React application is running on.
CMD – The command to run when the docker run command is run on the shell for this container.
Even though I’ve explained all of the different commands used in the Dockerfile, you can google any one of them to know what they do in more detail.
One thing that might seem weird to you is why we copy package.json separately and then all the other files separately.
This is done because while creating containers, docker uses caching and each layer is cached. Therefore, if we copy everything at once and then run NPM install, the NPM install command would run every time inside the container. The way we have done it, it will only run again if the contents of package.json have changed (pretty neat, eh?) else it will use the previously cached layer.
After you have successfully created your dockerfile, you can use it to create an image.
Running this command from where your Dockerfile exists will use your Dockerfile and create an image called my-react-app.
This image is then to be used to run a container with Docker.
With this command, we are running a container with the image my-react-app, naming the container my-react-application and binding the port 3000 of the host machine to the port 3000 of the docker container (that we had exposed in the dockerfile). The flag -d is used to run the container in a detached mode in the background.
If your command was run successfully, you’ll be able to check out your application on port 3000 in your browser, congratulations! We won’t actually be needing this though when we run the container through docker-compose later with Nginx .
nginx as a reverse proxy
Even though I assume you do know what Nginx is and how it serves multiple purposes , I’ll just explain in brief how we are planning to use Nginx as a reverse proxy for our goal.
A reverse proxy is basically a web server that sits in front of your application servers and routes the traffic coming from clients to different application servers. The application servers maybe Node, React or basically just about any technology. For other Nginx uses and benefits I would highly recommend you to take a read here – Nginx.
In our case we want to route traffic to a single React application but you would like to use Nginx as a reverse proxy to route traffic to different application servers if you have many running on a single machine.
You actually don’t need to set up Nginx on your machine as we’ll be using Docker to create a container with the Nginx image and with personal experience I kind of do like this method of working with Nginx as I think it is much cleaner and easier to operate.
So, create a folder called Nginx (or anything you’d like) and inside that folder we first need to create an Nginx config file which would look something like this :-
Nginx config file
You can name this file anything but be sure to have the extension as .conf , Nginx actually works on the basis of these .conf files. You do not need to understand most of the things written in this file (even I do not 😛 ) but the main things here are location and proxy_pass .
So basically, we are routing all the requests to the location “/” to “http://my-react-app:3000” . Just hold onto your seats for now, we’ll see where this comes from just next.
Note that you can create different conf files for different application servers you want to route to but make sure you name them appropriately.
The other file we would need in this Nginx directory is our good old Dockerfile, perhaps the simplest one you’ll ever write.
You know what the copy command does write, so we are basically just copying our conf file into the directory Nginx expects it to be in (inside the container we’ll be starting).
You can now successfully create you Nginx container as well but it won’t be of any use as of now.
Docker compose is a great tool to have to manage all your micro-services and containers.
It makes it super easy to deploy multiple containers at once and for them to communicate with each other. Make sure you have it installed though.
What you need to do is create a docker-compose.yml file and write this configuration in it :-
This is what our docker-compose file would look like. Both the build properties here are directories to both our services respectively and docker-compose expects a Dockerfile to exist in both these directories as it will use that Dockerfile to run the containers from.
We also expose ports from both the services here, (80 & 443 from Nginx as those are the ports for HTTP and HTTPS and that is how our Nginx would be exposed to the world). ports can be thought of as an alternative to the -p flag that is used during the docker run command.
You can see how we have named our react service as my-react-app and this exactly what we had used in the proxy_pass as well. Now the two and two connect right?
The last thing to do is run the final docker-compose up command and see all your services in action.
docker-compose up -d
Now, when you visit the port 3000 on the browser – you’ll be able to see your React application live. Congratulations!!!
For other devops articles please check this link here – Devops .
If you would like to join a facebook group with other web developers including me, please join us here – Easy on the web facebook group .