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;
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.