Introduction
A reverse proxy improves website performance and security by intercepting incoming traffic requests and directing them to the appropriate backend servers. The simplest way to set up and manage a reverse proxy is to deploy both the proxy and the backend services inside Docker containers.
In this tutorial, you will learn how to set up a reverse proxy on Docker.
Prerequisites
- Docker installed.
- Docker Compose installed.
- Command-line access.
- Administrative privileges.
Configuring Nginx as Reverse Proxy for Docker Container
Setting up an Nginx container as a reverse proxy requires modifying the configuration of the original Nginx Docker image. The following tutorial uses Dockerfile and Docker Compose to simplify the creation of the custom proxy image and the container based on the image.
Follow the steps below to configure a Nginx container as a reverse proxy for containerized web services.
Step 1: Set up Project Directory
Setting up the correct project directory structure is vital since the proxy container is deployed with Docker Compose. To create the necessary directories, open a terminal and type the following command:
mkdir proxy proxy/includes proxy/ssl
Before proceeding to Step 2, go to the main project directory:
cd proxy
Note: Execute all the commands in this tutorial from the main project directory.
Step 2: Generate Keys and Certificates
Enable SSL encryption for your website by creating SSL certificates and keys. To ensure you generated all the necessary files:
1. Use the touch command to create one KEY and one CRT (certificate) file for each service:
touch ssl/[service-name].crt ssl/[service-name].key
The example below shows generating files for services example1 and example2:
touch ssl/example1.crt ssl/example1.key ssl/example2.crt ssl/example2.key
2. Use the openssl command to generate the contents of the files:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ssl/[service-name].key -out ssl/[service-name].crt
For example, to create the key and certificate for the example1 service, type:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ssl/example1.key -out ssl/example1.crt
Repeat the procedure for each service you want the proxy to control.
Step 3: Edit Proxy and SSL Configuration
The includes directory in Nginx contains the necessary proxy and SSL configuration files. Create the files for your deployment by following the steps below:
1. Create the proxy.conf file using a text editor, such as Nano:
nano includes/proxy.conf
2. Paste the following code into the file to set the correct headers, disable buffering, and set the HTTP version:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_intercept_errors on;
3. Save the file and exit.
4. Create the ssl.conf file:
nano includes/ssl.conf
5. Paste the code below to customize the session settings and list the accepted protocols:
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
6. Save and exit the file.
Step 4: Create 404 File
HTTP reports the 404 error when communication with a web server is established, but the requested data cannot be found. Customize the 404 response with the following steps:
1. Create an HTML file. The example below creates the file named page-not-found.html:
nano page-not-found.html
2. Write the HTML code for the page. Below is the code for a simple error page:
<html>
<head>
<title>Page Not Found
</title>
</head>
<body>
<h2>Proxy Backend Not Found
</h2>
</body>
</html>
3. Save the file and exit.
Step 5: Edit hosts File
All the services connected to the proxy are available via a single IP address. The steps below show how to register the services in the system's hosts file:
1. Use the docker network
command:
docker network inspect bridge
Find the IP address of the Docker host in the output showing the bridge network information.
By default, the Docker host address is 172.17.0.1.
2. Open the hosts file on your system:
sudo nano /etc/hosts
3. Add the following line for each of the services:
[docker-host-ip-address] [service-domain]
For example, to connect example1.test and example2.test with the 172.17.0.1 Docker host, type the following:
172.17.0.1 example1.test
172.17.0.1 example2.test
4. Save and exit the file.
Step 6: Set up Nginx Configuration File
Once you generate all the necessary files, proceed with the steps below to create the main Nginx configuration file:
1. Create the default.conf file with a text editor:
nano default.conf
2. Include a server block for each service and another block for bad requests (the 404 page). The example code below shows the configuration for example1 and example2 services.
You need to change the following values:
server_name
. Provide your service domain.ssl_certificate
andssl_certificate_key
. Use the files generated in Step 2.proxy_pass
. This line should contain the container IP address for each service, listening on port 80.
Note: If you do not know the service IP address, find the service network by listing the Docker networks with docker network ls
. Inspect the relevant service network with docker network inspect [service-network]
and locate the gateway address.
server {
listen 80;
listen 443 ssl http2;
server_name example1.test;
ssl_certificate /etc/ssl/certs/nginx/example1.crt;
ssl_certificate_key /etc/ssl/certs/nginx/example1.key;
include /etc/nginx/includes/ssl.conf;
location / {
include /etc/nginx/includes/proxy.conf;
proxy_pass http://172.20.0.2:80;
}
access_log off;
error_log /var/log/nginx/error.log error;
}
server {
listen 80;
listen 443 ssl http2;
server_name example2.test;
ssl_certificate /etc/ssl/certs/nginx/example2.crt;
ssl_certificate_key /etc/ssl/certs/nginx/example2.key;
include /etc/nginx/includes/ssl.conf;
location / {
include /etc/nginx/includes/proxy.conf;
proxy_pass http://172.21.0.2:80;
}
access_log off;
error_log /var/log/nginx/error.log error;
}
server {
listen 80;
server_name _;
root /var/www/html;
charset UTF-8;
error_page 404 /page-not-found.html;
location = /page-not-found.html {
allow all;
}
location / {
return 404;
}
access_log off;
log_not_found off;
error_log /var/log/nginx/error.log error;
}
3. Save the file and exit.
Step 7: Create Dockerfile
Add the files generated in this tutorial to the custom Nginx proxy container image. Follow the procedure below to complete this action using Dockerfile:
1. Create Dockerfile with a text editor:
nano Dockerfile
2. Save the following code into the file.
FROM nginx
COPY ./default.conf /etc/nginx/conf.d/default.conf
COPY ./page-not-found.html /var/www/html/page-not-found.html
COPY ./includes/ /etc/nginx/includes/
COPY ./ssl/ /etc/ssl/certs/nginx/
The code tells Docker to generate a new image based on the official nginx image. The image is then customized by adding the configuration files and directories from the local system.
Step 8: Configure compose.yaml
Docker Compose makes it easier to deploy and set up complex container configurations. The following steps show how to use Docker Compose for the proxy deployment:
1. Create the compose.yaml file:
nano compose.yaml
2. The YAML declaration in compose.yaml creates the proxy service and connects it with service networks:
version: '2'
services:
proxy:
build: ./
networks:
- example1
- example2
ports:
- 80:80
- 443:443
networks:
example1:
external: true
name: example1_default
example2:
external: true
name: example2_default
3. Save and exit the file.
The example above defines two networks, example1 and example2. The configuration connects them with the corresponding external networks, example1_default and example2_default. Replace those values with the network information from your system.
Step 9: Start Reverse Proxy
With all the configuration files ready, use the procedure below to create and start an Nginx proxy:
1. Build the proxy image by executing the following command:
docker compose build
2. Run a proxy container in the detached mode:
docker compose up -d
3. Test if the container is running by typing the following command:
docker ps
The command lists the running container. Find the proxy container in the list to confirm it is running.
4. Test the configuration by using the curl command
to communicate with a service domain:
curl example1.test
The output shows that the proxy forwarded the request to the correct service.
Conclusion
After reading this article, you should know how to set up an Nginx reverse proxy for Docker containers. The tutorial went over the necessary Nginx and Docker configuration files and listed the necessary steps to connect backend containers with the proxy.
To learn more about Nginx reverse proxy outside the Docker environment, read How to Set up and Use NGINX as a Reverse Proxy.