DEV Community

Morning Redemption
Morning Redemption

Posted on

Learning Nginx as a MERN developer. [Part 1]

In this tutorial, we’ll walk through how to serve a Dockerized React frontend behind Nginx while proxying requests to a Node.js backend. This is a practical guide for anyone looking to containerize their full-stack application and make it production-ready with a simple reverse proxy.

Prerequisites

Before we dive in, make sure you have:

Familiarity with the terminal / command line — you’ll be running Docker commands and editing configuration files.

A working understanding of Node.js and npm (or any backend framework you’re containerizing).

Basic networking concepts — understanding ports, host vs. container networking.

Docker installed — Docker Desktop on Windows/Mac or Docker Engine on Linux.

docker-compose — usually comes bundled with Docker Desktop.

Git — to manage and clone your code repository.

Basic knowledge of Docker concepts — images, containers, volumes, and networks.

By the end of this tutorial, you’ll have:

A React frontend served by Nginx inside a Docker container.

A Node.js backend running in its own container, accessible via /api/ routes.

A working docker-compose.yml orchestrating frontend, backend, and MongoDB.

This setup is production-lean, easy to extend with SSL, caching, or real-time features in later posts.

What's Nginx and why do we even need it,

👾I can deploy on vercel

If you're familiar with Vercel/Netlify that's what nginx does, Its a little bit more complicated and a little less expensive.

Below mentioned are the uses of nginx.

1- Serving static File
2- Reverse Proxy
3- Load Balancer
4- SSL/TLS termination
5- Caching Layer

There are multiple things we need to discuss but let's first look at the Dockerfile of the frontend folder

Use this github repository and clone it https://github.com/pksri1996/Nginx/

Assuming you went through my Docker blog

What this part essentially does is, it created 2 images and the first image is

FROM node:18 AS build

NOw this build is a temporary image and it will not become a wholesome container, The container which will persist using this Dockerfile will have an alpine image of nginx and it will copy the nginx.conf file from the build image to this container's image and eventually start a VERY LEAN nginx server only to serve static file.

I hope you got this if not.

Go back there and read it (Docker)

Anyway now let's focus on the nginx.conf file and look at where we are performing each one of the roles listed above.

1- Serving static File

Now this is something which is the primary function of nginx.

server {
    listen 80;

    root /usr/share/nginx/html;
    index index.html;

    server_name _;
Enter fullscreen mode Exit fullscreen mode

This will listen on port 80 for anything, basically it will keep itself very low until a request comes and the it goes to /usr/share/nginx/html and serve the index.html file present in the docker container. This request can come from anywhere in this code snippet.

server_name is what Nginx uses to tell different domains apart.
So, if you set up two server_name values, each one can point to its own root section — letting you serve different sites from the same server.

The _ is like a wildcard placeholder. It basically says: “if nothing else matches, send the request here.”

Now that we understood how the static files are served, Let's move to the next section, i.e. proxy.

2- Reverse Proxy

Now Proxy is when you use a different server to reach a website, essentially hiding your identity from the website's server. Reverse proxy is the website not exposing it's backend (In this case the backend is on port 5000) to the internet, It only allows clients to make request to nginx server, yes even the backend ones and nginx routes those requests to our backend servers.

Pictorial representation of proxy vs reverse proxy.

This is an effective way

location /api/ {
        proxy_pass http://backend:5000/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
Enter fullscreen mode Exit fullscreen mode

Now the first statement is the only one that really matters. backend:5000 is what routes all requests straight to the container named backend, and that’s it.

Everything else is just there to make sure that if your server or clients are trying to use more complex protocols like WebSockets, the requests don’t get stuck in the HTTP cache and end up reusing an old response.

If you want to understand more, feel free to use GPT or you can simply use all of these. I'm sure you will do you are capable of doing research on this.

This is just a small pat on the back saying

Now I am not claiming this is the be all and end all of nginx. Just like Docker, nginx is a big concept, but this should do for now. We will discuss the rest of the roles in my next blog.I will also touch on a few more things on it.

Kindly note that unlike docker this is more like Chemistry and not physics. You could learn just one formula and get perfect with docker, with nginx it's more like exceptions, a lot of things to memorise etc.

Top comments (0)