A practical guide to implementing reverse proxy using dockerized nginx with multiple apps

Max Shahdoost
4 min readJun 9, 2023
Nginx Reverse Proxy

In this article, we are going to cover a very common practice architecture used in many services called reverse proxy and we are going through all the details on how to setup a reverse proxy using an Nginx server and how can we manage multiple apps on a single server instance using 80 and 443 ports with SSL credentials.

Important Note:
Reading the below article carefully to cover security practices is a must after this article.
Nginx reverse proxy security and performance best practices
https://maxtsh.medium.com/nginx-reverse-proxy-security-and-performance-best-practices-e47f599c8fed

First of all, let’s check the architectures’ UML and see how it is actually demonstrated:

A simple Nginx reverse proxy UML

As you can see, we have multiple applications and we would like to connect them to a proportional amount of domains or subdomains but if a classical way of doing things, it is impossible to do so because once you manipulated the servers’ port 80 and port 443, you can’t point your domains/subdomains to your server unless you’re going to use them along with their respective port numbers like:

my-website.com:8090

That is really a terrible thing to happen because we need to use SSL certificates to secure the user's connections to web our services but we wouldn’t be able to do so.

According to the UML diagram, we need to use an Nginx service as a watcher in order to handle the requests coming to our server and redirect the traffic to the proper application without the user being affected by anything in the front.

Step 01:
Create a folder in the root directory of your server and give it a name for example reverse-proxy and jump into it like below:

mkdir reverse-proxy
cd reverse-proxy

Step 02:
Create a folder and call it certs or whatever you like, which is going to keep your SSL certificates and keys.

mkdir certs

Step 03:
Create a nginx.conf file, we’re going to write our reverse-proxy setup inside this file so this is the core of our task here.

touch nginx.conf
# first.com
server {
listen 80;
server_name www.first.com firstapp.com;
location / {
proxy_pass http://first_container:first_port;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 443 ssl;
server_name www.first.com first.com;
ssl_certificate /etc/nginx/certs/ssl_cert.crt;
ssl_certificate_key /etc/nginx/certs/ssl_key.key;
location / {
proxy_pass http://first_container:first_port;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}

# second.com
server {
listen 80;
server_name www.second.com second.com;
location / {
proxy_pass http://second_container:second_port;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 443 ssl;
server_name www.second.com second.com;
ssl_certificate /etc/nginx/certs/ssl_cert.crt;
ssl_certificate_key /etc/nginx/certs/ssl_key.key;
location / {
proxy_pass http://second_container:second_port;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}

In the above code, we are telling our nginx to watch for traffic coming through first.com and second.com Which are our imaginary domains ( you can do it with subdomains as well ) and proxy pass them to different applications dockerized and are up and running on our server pointed to specific ports with specific docker container names.

Edit it as you wish and don’t forget to upload your SSL certificates to the certs folder in order for this config to work then save it.

Step 04:

Now create a docker-compose file because we are not going to use this nginx as a service in our server but as a dockerized app instead.

touch docker-compose.yml
version: '3'

services:
nginx:
image: nginx:latest
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./certs:/etc/nginx/certs

networks:
default:
external:
name: nginx-proxy-net

We are using the latest nginx image from the docker hub and calling our container nginx-proxy which is optional and you can call it whatever you like.
We will map and listen on the server port 80 to docker host port 80 and also port 443 to 443 on the docker host.

Something important here is that we need to create a network for our nginx reverse proxy and add all our applications to the network in order for all this to work, we also call the network nginx-proxy-net.

We are all set here, now you need to run all the applications’ docker containers with their respective ports on the server which you added to your nginx.conf file.

After you run all the apps, you need to run the nginx reverse proxy container, if everything is done correctly, now you are listening on ports 80 and 443 with your SSL certificates and your nginx reverse proxy is handling the traffic coming through your server and dispatch them to respective apps.

sudo docker-compose up -d

Don’t forget that you need to add your app's containers to the proxy network you have named in your reverse proxy docker-compose file.

I hope this article could be helpful to you, please feel free to comment and ask questions.

--

--

Max Shahdoost

A highly passionate and motivated Frontend Engineer with a good taste for re-usability, security, and developer experience.