Nginx docker container serving a front end react app

Mohamed Belkamel
3 min readMay 6, 2020

--

Serving react front ends can be done in many ways, depending on your needs, but one effective way of doing it, if for sure using nginx, so stick with me

The way you might be doing it right now is using your rest api (express / rails), but this puts unwanted weight and traffic on your api, instead what we could do is seperate the serving of the front-end from the back-end.

exemple of how nginx saves traffic from Rest api

as seen above nginx knows if you browser is asking for the html and javascript code, and obeys as follows, HOW? you might be wondering, well lets see:

FUN PART

prerequisite you only need docker installed on your machine to run the following

  1. create the nginx docker container:

In order for nginx to serve our front-end it needs to have its files first right? duh!, lets create a dummy client app using

npx create-react-app client

then we will need a Dockerfile:

FROM node:12-alpine as buildWORKDIR /appCOPY package*.json ./RUN npm install --productionCOPY . .RUN npm run build

what this code will actually do, assuming its inside your client app its ging to fetch an nginx image of node 12, alpine which is basically a lightweight version, copy the package files in order to install the dependencies, and copy the source code and build the final files that nginx is going to serve tp the public.

2. Inthe same file add the following.

FROM nginx:stable-alpineCOPY --from=build /app/build /bin/wwwCOPY nginx/nginx.conf /etc/nginx/conf.d/default.confEXPOSE 80CMD [ "nginx", "-g", "daemon off;" ]

“what gibberish is this”, you might be wondering, relax, basically for nginx in order to function correctly it need to have the a config file and servers them through port 80 (equivalent to “localhost ”without any appended ports), the above is going to copy the folder generated by our:

RUN npm run build

and paste it inside our little cute nginx Virtual machine-ish container, so the next time a user requests our website nginx doesnt have to look around a lot to responde. Next we need a config file to let nginx know where our app is located in the container:

3. create a file inside a folder called “nginx ”in your client folder and call it nginx.conf as we specified in our Dockerfile and paste the following

server {listen 80;location / {     root /bin/www/;     index index.html index.htm;     try_files $uri $uri/ /index.html;}    location /api {    proxy_pass http://{YOUR_API}; #http://localhost:5054;    proxy_http_version 1.1;    proxy_set_header Upgrade $http_upgrade;    proxy_set_header Host $host;    proxy_cache_bypass $http_upgrade;}}

so the above nginx.conf/ tells nginx, “alright listen up, requests that look like this => http://exemple.com/, get them to the index.html file inside the /bin/www NOTE: it needs to be an absolute path. paths that have a trailing /api , like http://exemple.com/api, go to the backend “

ALMOST DONE

okay if you’re going to use this, you most likely want to orchesrate it using docker-compose, if so make sure you have your ports specified and you’re on the correct network more on that later, but you might want something like this:

version: "3.5"services:  api:     build: .      networks:      - app-network     ports:      - "5054:5054"  client:     build: ./client/     restart: unless-stopped     ports:      - "80:80"     networks:      - app-networknetworks:   app-network:

here we declared two services, our api and our client app, as you can see they share the same network so they can talk to each other like http://api:5054

rather than http://localhost:5054 , as we know that wouldn’t work because these two apps are not hosted on the HOST machine.

NEXT step:

here is a trick, open up chrome dev tools, and you’ll see that the html file is coming from “server: nginx” meanwhile route requests like /api are coming from “server: express” or rails api

--

--