How to Set up Nginx as Reverse Proxy for Docker Container

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.

How to Set up Nginx as Reverse Proxy for Docker Container.

Prerequisites

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
Generating an SSL key and certificate for a web service.

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.

Finding the IP address of the Docker host.

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
Editing the hosts file on the local system.

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 and ssl_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
Building a custom proxy image with Docker Compose.

2. Run a proxy container in the detached mode:

docker compose up -d
Running a container based on the created custom proxy image.

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.

The proxy container in the list of the running Docker containers.

4. Test the configuration by using the curl command to communicate with a service domain:

curl example1.test
Using curl to test the connection with a service.

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.

Was this article helpful?
YesNo
Marko Aleksic
Marko Aleksić is a Technical Writer at phoenixNAP. His innate curiosity regarding all things IT, combined with over a decade long background in writing, teaching and working in IT-related fields, led him to technical writing, where he has an opportunity to employ his skills and make technology less daunting to everyone.
Next you should read
How to Install Nvidia Drivers on Ubuntu 20.04
March 23, 2021

Ubuntu 20.04 comes with an open-source Nouveau GPU driver out of the box. This driver does not always take...
Read more
Bare Metal Cloud Portal Quick Start Guide
March 23, 2021

Follow the sections in this Bare Metal Cloud Portal guide to learn how to navigate through the portal. This...
Read more
How to Deploy a Bare Metal Cloud Server
March 23, 2021

This article shows how to deploy a new Bare Metal Cloud server in nine simple steps. Follow the instructions...
Read more
How to Use the vmstat Command
March 18, 2021

The vmstat command is a Linux monitoring utility used to see various system statistics and to diagnose...
Read more