Creating a Reverse Proxy with Docker
Contents
Contents
Introduction
This blog post will explain the concept of a reverse proxy, and will demonstrate the steps that need to be taken in order to create a Nginx reverse proxy inside of Docker.
The concept of a reverse proxy is very simple, a client computer will connect to a central point that will pass their connection on to the desired destination. For example, lets take a look at the diagram below. The client can connect to two domains, web1.test.net and web2.test.net. Regardless of which domain the user wants to connect to the connection will always be sent to the front facing reverse proxy. The reason for this is that the dns record for web1.test.net and web2.test.net point to the same location.
The question arises as to how the reverse proxy will figure out where forward the connections it receives. Notice that between the Client Computer and the Reverse Proxy the connection is using HTTPS, however, from the Reverse Proxy to the destination it is HTTP. This means that the Reverse Proxy is capable of viewing the plain text HTTP. Through this the Reverse Proxy can learn which domain the user wants to connect to.

Installing Docker and Docker Compose
This section will show how to install Docker and Docker Compose on CentOS 7. You can use your own favorite distribution, you will have the choice of getting Docker from the distributions repositories or the official Docker repository. The following installs Docker from the official repository on CentOS 7.
Run this one liner to add the official Docker repository, install Docker, start it, and enable it so it will start on boot.
|
|
Run this one liner to install Docker compose from the official Docker Github.
|
|
Giving a User Access to Docker
You will notice that you need to use sudo to run any docker commands as a regular user. You can either use the root account to make life easy, or you can add your current user into the docker group which will give user access.
Run the following to add a user named user to a group named docker. Restart the system and you will have access to Docker without sudo.
|
|
Docker Root Access Issue
NOTE: If you have given a regular user access to use Docker, this user is essentials root on the system. This issue stems from the fact that Docker itself is run as root. Run the following as a demonstration, and make a decision for yourself whether or not this is acceptable.
Enter a new container and bind the / of the host to /root of your container.
|
|
chroot into the host system. This will give you access to the host system running the Docker container as root.
|
|
As you can see we are able to access the host system and list the container itself being run.
Creating Reverse Proxy
Configure DNS
The first step is to setup a DNS server that will point to the server with all the Docker containers on it. The IP address of my server is 10.0.0.200, this is also the IP address that the front facing server will be exposed under.
In order to make things simple make a A record that points to the server itself, I named mine reverseproxy.test.net and gave it the IP address of 10.0.0.200. In order to not type the IP address over again create a CNAME record that points to the A record created.
In order to confirm that everything is working ping the domains web1.test.net and web2.test.net from a client machine, make sure that the DNS resolves the IP address and that the server is reachable.
Creating a Docker Compose Configuration File
Create a directory in which all the files will be stored.
|
|
Create a file located at ~/reverseproxy/docker-compose.yml which has the following contents:
|
|
This file describes the containers and will be created, and the parameters to be given to each container.
The reverseproxy container is the reverse proxy itself, as can be seen it exposes ports 80 and 443 for web traffic. There are also a file and folder binded to it. ./files/reverseproxy/nginx.conf is the configuration for Nginx, and ./files/reverseproxy/ssl is a folder that will contain the certificate for TLS.
Next we see two other containers, web1.test.net and web2.test.net. These are our back end services that we will connect to through the reverse proxy, they are not exposed directly to the network. You can see through the image parameter that they are using the Apache webserver. These containers also bind a volume that will contain the index.html file.
Lastly, it is best to point out that when we create these containers with Docker Compose a network will be created. This is a internal network for the Docker containers, inside this network there is also a built in DNS server that Docker provides. We will not be accessing the reverseproxy container so we do not need any domain for it. However, web1.test.net and web2.test.net will resolve to the containers IP address inside of the Docker network, through this method the reverse proxy will be able to locate the container.
Nginx Reverse Proxy Configuration
Now we will create the configration for the Nginx reverse proxy. Begin by creating the folder that this will be located in:
|
|
Create the following file in the location ~/reverseproxy/files/reverseproxy/nginx.conf:
|
|
The must important part of this configuration to understand is that when connections are received as HTTP they will be redirected to HTTPS using return 301 https://$host$request_uri;. When received as HTTPS they will be proxied using the proxy_pass "http://$http_host"; line. Note that we specify a DNS using resolver 127.0.0.11;, this is the internal Docker DNS that will be used to locate the IP address of the containers.
Creating a Self Signed Certificate
Since our Nginx reverse proxy is using HTTPS we will create a self singed certificate. This certificate will be created as a wildcard for the test.net domain.
Create a folder and generate the selfsigned certifcate.
|
|
When prompted with Common Name enter the wild card domain, like the following:
|
|
Creating Content for End Points
Create folders for the index.html files that will be served to the Apache webservers, and create the files themselves.
|
|
At this point your file structure should look like this:
|
|
Testing Reverse Proxy
Run the following which will start up all the containers. It may take a second or so to download all the images.
|
|
Now that the containers are running connect to the domains web1.test.net and web2.test.net from a browser. You should get a message saying that you are using a self singed certificate, once you pass that you will see the contents of the index.html file. If you have followed the instructions exactly, remember to either disable the firewall, or allow ports 80 and 443.