Often in large application ecosystems a common nginx is used as a loadbalancer and reverse-proxy for many applications. In a previous post of this series, we have seen how nginx can be used to load balance traffic multiple containers.
In this post, we're going to see how we can use nginx as a reverse-proxy which would route requests to different containers based on path.
What we are going to do
- create an express application, with path
/app-first
path and launch it in a container - create an express application, with path
app-second
path and launch it in a container - create an nginx container, and have 2 paths configured in it. path-1 forwards the request to first container, and path-2 forwards the request to second container
Create the directories
mkdir first-app
mkdir second-app
mkdir nginx-docker
Create the first application
I just created a very basic nodeJs application. The app.js looks like the following
var express = require("express");
var app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.get("/app-first", function (req, res, next) {
res.send({ title: "Express", application: "Application 1" });
});
app.listen(3000, () => console.log("Running on http://localhost:3000"));
The package.json looks like the following
{
"name": "express-with-env",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "~4.16.1"
}
}
and in parallel to these, the Dockerfile looks like the following
FROM node:12-slim
WORKDIR /app
COPY ./package*.json ./
RUN npm install
COPY ./ ./
EXPOSE 3000
# Run the code
CMD [ "npm", "start" ]
Create the second application
The second application is exactly like the first application, except, it runs on PORT 4000, and exposes path /app-second
. the app.js looks like the following
var express = require("express");
var app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.get("/app-second", function (req, res, next) {
res.send({ title: "Express", application: "Application 2" });
});
app.listen(4000, () => console.log("Running on http://localhost:4000"));
and the Dockerfile looks like the following
FROM node:12-slim
WORKDIR /app
COPY ./package*.json ./
RUN npm install
COPY ./ ./
EXPOSE 4000
# Run the code
CMD [ "npm", "start" ]
The packageJSON looks exactly like the first application
Create the nginx config
Go to the nginx-docker directory and create nginx.conf file
upstream first-app {
server 172.17.0.1:3000 weight=1;
}
upstream second-app {
server 172.17.0.1:4000 weight=1;
}
server {
location /app-first {
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://first-app;
}
location /app-second {
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://second-app;
}
}
Create a dockerfile for the nginx and here's what it looks like
FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
Create the images and run the containers
Go to first-app
directory and build the image
sudo docker build -t first-app .
Go to the second-app directory and build the image
sudo docker build -t second-app .
Run the images now
sudo docker run -p 3000:3000 -d first-app
sudo docker run -p 4000:4000 -d second-app
Now, if you open http://localhost:3000/app-first in browser, you should get the following JSON
{
"title": "Express",
"application": "Application 1"
}
and by opening http://localhost:4000/app-second, you should get
{
"title": "Express",
"application": "Application 2"
}
You see, the applications are running in different ports. Your target is to expose them both in the same port.
Go to the nginx-docker directory and build the nginx image and run it.
sudo docker build -t nginx-proxy .
sudo docker run -p 8000:80 -d nginx-proxy
Now you'll be able to see both the applications running in port 8000, as
PS:
We wrote code for 2 applications(first-app and second-app) here, and wrote configuration for the third(nginx). We created their docker images, and we ran those images. Of course, these are too many commands to handle. In our next post, we'll look into docker-compose
to simplify these image building and running.
The code for this tutorial is checked in at https://github.com/tirthaguha/container-reverse-proxy
Top comments (0)