Nginx Reverse Proxy using Docker

Nginx Reverse Proxy using Docker

In todays web architecture demand agility and scalability are essential factors. Managing services while maintaining optimal performance is a necessity in the present scenario.

This is where reverse proxies come in , a simple yet efficient concept which provides the flexibility to streamline the interaction or communication between clients and services.

The concept of reverse proxy as illustrated by the diagram acts like a receptionist in a building with various departments and sectors. The receptionist successfully redirects a customer or visitor to the appropriate department. They are responsible for guiding visitors , handling queries and ensuring distribution the various departments.

Some of the use cases of reverse proxies are

  • Load Balancing for scalability

  • Termination of SSL and TLS

  • Map subdomains to specific paths

In this blog we are going to setup a reverse proxy using nginx and docker containers , something that can be easily setup in any system.

Building the main app

The code for this can be found here -> Nginx reverse proxy

Lets start by building the main app which will act as the proxy , we will name this main app.

Write the docker file to display a simple html page on hitting the / endpoint of this app

FROM nginx:stable-alpine
COPY index.html /usr/share/nginx/html/index.html

The html file index.html is this

<h1>This is the main app</h1>

Now lets write a simple docker compose file which runs this app

version : '3.7'
services :
  web:
    build: .
    ports:
    - "8080:80"

Lets start the docker compose by running the following command

docker-compose up

Head to localhost:8080 and you should see this

Lets create the two different apps too in a similar fashion with two html files and same Dockerfile

This is html file for app1
<h1>This is APP 1</h1>

This is html file for app2
<h1>This is APP 2</h1>

Change the docker compose file to start these two containers

version : '3.7'
services :
  web:
    build: .
    ports:
    - "8080:80"
    restart: always
  app1:
    build: ./app1/
    ports:
    - "8085:80"
    restart: always
  app2:
    build: ./app2
    ports:
    - "8010:80"
    restart: always

On heading to port 8085 and 8010 you should see this

Writing the nginx config

We write the nginx config file , we want to do such that on hitting requests to /apps it proxies between app1 and app2 and on / endpoint it just displays main page.

This is the nginx config we write.

worker_processes  1;  ## Default: 1
worker_rlimit_nofile 8192;

events {
  worker_connections  4096;  ## Default: 1024
}

http {

  upstream cloud_server_com {
    server app1:80;
    server app2:80;
  }

  server {
    listen   80;

    location /app/ {
      proxy_pass      http://cloud_server_com/;
    }

    location / {
      root   /usr/share/nginx/html;
      index  index.html;
    }

  }
}

The upstream defines the group of servers which we club together. Here we specify the container names as defined in the docker compose file along with their ports.

The location helps nginx define how to handle requests at specific endpoints. The /app/ sends requests to the cloud_server_com upstream which is in turn our two app containers.

The proxy_pass determines where requests will be redirected.

Now our docker compose file needs to be able to read this config so we modify our compose file

version : '3.7'
services :
  web:
    build: .
    ports:
    - "8080:80"
    volumes:
      - ./config/nginx.conf:/etc/nginx/nginx.conf
    restart: always
  app1:
    build: ./app1/
    ports:
    - "8085:80"
    restart: always
  app2:
    build: ./app2
    ports:
    - "8010:80"
    restart: always

Running the containers

Run docker-compose up and head to browser to see how reverse proxy works

This is the main app running on the / endpoint

On hitting /app/ endpoint however it returns two different servers

The proxy sends requests to both app1 and app2 one at a time.

This is how we make a reverse proxy using only docker and nginx.