---
title: "Create an NGINX Reverse Proxy in Docker and Learn 1 New Skill!"
description: "Learn how to set up an NGINX reverse proxy in Docker using PHP-FM and NodeJS in this step-by-step tutorial."
canonical: "https://adamtheautomator.com/nginx-reverse-proxy-in-docker/"
---

# Create an NGINX Reverse Proxy in Docker and Learn 1 New Skill!

> Learn how to set up an NGINX reverse proxy in Docker using PHP-FM and NodeJS in this step-by-step tutorial.

Source: https://adamtheautomator.com/nginx-reverse-proxy-in-docker/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Create an NGINX Reverse Proxy in Docker and Learn 1 New Skill!](https://adamtheautomator.com/wp-content/uploads/2021/07/How-to-Set-up-an-NGINX-Reverse-Proxy-in-Docker-Step-by-Step.jpg)

# Create an NGINX Reverse Proxy in Docker and Learn 1 New Skill!

[![](https://secure.gravatar.com/avatar/f08b754bc0dce1c76685f6afa93185ecfb6f861fd14f993286e06bba69eaeb8b?s=192&d=mm&r=g)Adam Listek](https://adamtheautomator.com/author/alistek/)31 July 20216 min. read

Categories: [DevOps](/category/devops/)

Tags:[Docker](/tag/docker/)[NGINX](/tag/nginx/)

Table of Contents

*   [Prerequisites](#h-prerequisites)
*   [Creating an PHP-FPM NGINX Reverse Proxy in Docker](#h-creating-an-nginx-php-fpm-reverse-proxy)
*   [Proxying Both NodeJS and PHP-FPM from NGINX](#h-proxying-both-nodejs-and-php-fpm-from-nginx)
*   [Conclusion](#h-conclusion)

Do you need powerful web servers to handle requests to your Docker application? Using an NGINX reverse proxy in Docker gives you the ability to handle and manage web application requests to and from a containerized application in various ways.

In this article, you will learn how to create an NGINX Reverse Proxy in Docker and configure the container to reverse proxy requests to and from another container. Read on to learn more!

## Prerequisites

To follow along with this tutorial, be sure you have the following:

*   [Docker Desktop](https://www.docker.com/products/docker-desktop) – This tutorial uses version 3.5.2.
*   Windows 10 – The tutorial uses Windows to run Docker on, but the same general steps can also be applied to Linux or macOS.
*   The [Docker engine](https://docs.docker.com/engine/install/) if you’re on Linux.

> _All examples in this tutorial will use a minimal Linux Distribution called [Alpine Linux](https://alpinelinux.org/about/), running the latest [NGINX](https://adamtheautomator.com/nginx-on-docker/) version available. As of this writing, v1.21.1 is the latest version._

Related:[Getting Started with NGINX on Docker](https://adamtheautomator.com/nginx-on-docker/)

## Creating an PHP-FPM NGINX Reverse Proxy in Docker

One of the most popular programming languages, PHP is often a use case for a reverse proxy. [PHP-FPM or Fast CGI Process Manager](https://www.php.net/manual/en/install.fpm.php) is a great product to use for proxying traffic in the PHP world. Using PHP-FPM in a Docker container and NGINX in another, you can set up PHP-FPM to listen and respond to requests on a network port, assisting in networking two containers together.

> _Bonus! This tutorial will also provide examples of using NodeJS as a reverse proxy throughout as well. Be on the lookout for the NodeJS callouts._

Let’s now set up both an NGINX container and a PHP-FPM Docker container to see how they work together proxying requests from the browser through NGINX to PHP-FPM backend and back.

1\. First, create a directory to contain your configuration files. This directory will contain all of the configuration files needed to provision both containers. In this example, the directory _C:\\Articles\\NGINX-PHP_ is used.

2\. Next, create the [Dockerfile](https://docs.docker.com/engine/reference/builder/) with the following contents. The below Dockerfile will tell the Docker engine to download the `nginx:mainline-alpine` image from the [Docker Hub repository](https://hub.docker.com/_/nginx) and will copy the NGINX configuration file you’ll be creating into the image to provide a custom NGINX configuration.

```docker
# The image to pull the base configuration from
FROM nginx:mainline-alpine
# The directory where additional files will be referenced
WORKDIR C:\Articles\NGINX-PHP
# Copy the custom default.conf from the WORKDIR (.) and overwrite the existing internal configuration in the NGINX container
COPY ./default.conf /etc/nginx/conf.d/default.conf
```

> _Grab the [NodeJS Dockerfile](https://github.com/Adam-the-Automator/Scripts/blob/main/how-to-set-up-an-nginx-reverse-proxy-in-docker-step-by-step/nodejs/dockerfile) to set up the NodeJS Docker image in the ATA Scripts Github repository!_

3\. Next, create the file _docker-compose.yml_ file, containing the following. This [Docker Compose](https://docs.docker.com/compose/) file will tell Docker to create two containers, `web` and `php` running NGINX and PHP-FM, respectively.

```yaml
# The specification version of docker-compose
version: "3.9"
# The collection of applications composing this service
services:
  # The NGINX custom container, and the name, web, will function as the host name of the container
  web:
    # Instead of referencing image: nginx:mainline-alpine here, use build to
    # reference the current directory (.), which will look for a dockerfile
    # by default. In this tutorial, this is C:\Articles\NGINX-PHP
    build: .
    # The external directory location to map to an internal location
    volumes:
      - C:\Articles\NGINX-Content:/usr/share/nginx/html
    # The external port mapping to internal port mapping
    ports:
      - "80:80"
  # The name, php, will also function as the host name of the container
  php:
    image: php:fpm-alpine
    ports:
      - "9000:9000"
    # It is important that both containers can reference the same files
    volumes:
      - C:\Articles\NGINX-Content:/usr/share/nginx/html
```

Related:[Everything You Need to Know about Using Docker Compose](https://adamtheautomator.com/docker-compose-tutorial/)

> _Grab the [NodeJS Docker Compose file](https://github.com/Adam-the-Automator/Scripts/blob/main/how-to-set-up-an-nginx-reverse-proxy-in-docker-step-by-step/nodejs/docker-compose.yml) to set up the NodeJS Docker image in the ATA Scripts Github repository!_

4\. Create the NGINX configuration file, _default.conf_, with the following. The file below defines a short NGINX configuration that creates a site listener and sends content requests to the PHP container.

```yaml
server {
    # The port to listen on
    listen 80;
    # The root directory, which must exactly match the internal volume share
    root /usr/share/nginx/html;

    # For all files with the PHP extension run the following
    location ~ ^/.+\.php(/|$) {
        # Pass the request to the host "php" and port 9000 (default PHP-FPM port).
        # The "php" host name is generated from the application name in the
        # Docker Compose file that was previously defined.
        fastcgi_pass  php:9000;
				# Include the default NGINX FastCGI Parameters
        include       fastcgi_params;
				# Define one additional parameter telling PHP-FPM where to find the file
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
```

> _Grab the [NodeJS NGINX configuration file](https://github.com/Adam-the-Automator/Scripts/blob/main/how-to-set-up-an-nginx-reverse-proxy-in-docker-step-by-step/nodejs/default.conf) to set up the NodeJS in NGINX in the ATA Scripts Github repository!_

5\. Open a terminal session and navigate to the _C:\\Articles\\NGINX-PHP_ directory.

6\. Run the command, `docker-compose up` to generate and start your custom service. This action will bring up both containers.

![Starting the NGINX and PHP-FPM containers via Docker Compose.](https://adamtheautomator.com/wp-content/uploads/2021/07/Untitled-2021-07-31T152043.387.png)

Starting the NGINX and PHP-FPM containers via Docker Compose.

7\. Next, create a PHP file called _index.php_ in _C:\\Articles\\NGINX-Content_ and paste the following contents. This file will be used to test that NGINX can serve and process files via PHP. The `phpinfo()` command will output the PHP informational page to verify that the container is working.

```php
<?php phpinfo(); ?>
```

> _Instead of a PHP file, download the [index.js](https://github.com/Adam-the-Automator/Scripts/blob/main/how-to-set-up-an-nginx-reverse-proxy-in-docker-step-by-step/nodejs/index.js) file in the ATA Scripts Github repository!_

8\. Finally, open a web browser and navigate to [http://localhost/index.php](http://localhost/index.php*) to verify that NGINX serves up the PHP file as expected. In the below example, PHP is returning version 8.0.8, but your version may vary.

![Demonstrating that the PHP file properly works.](https://adamtheautomator.com/wp-content/uploads/2021/07/Untitled-2021-07-31T152206.033.png)

Demonstrating that the PHP file properly works.

## Proxying Both NodeJS and PHP-FPM from NGINX

Now that you have proxied both PHP and NodeJS individually, how would you go about proxying both backends simultaneously? Perhaps, you have a complex application that consists of both NodeJS and PHP components. For this to work, you will need to extend your Docker Compose file to include both backends.

1\. First, create a directory to contain your configuration files. In this example, the directory _C:\\Articles\\NGINX-Both_ is used.

2\. Create the _Dockerfile_ and paste using the following contents. So far, not much difference at all from building PHP-FPM or a NodeJS container individually.

```docker
# The image to pull the base configuration from
FROM nginx:mainline-alpine
# The directory where any additional files will be referenced
WORKDIR C:\Articles\NGINX-Both
# Copy the custom default.conf and overwrite the existing internal configuration
COPY ./default.conf /etc/nginx/conf.d/default.conf
```

3\. Next, create the file _docker-compose.yml_ file, containing the following. You’ll now see that another container has been introduced called `node`.

```yaml
# The specification version of docker-compose
version: "3.9"
# The collection of containers making up your application
services:
  # The NGINX custom container
  web:
    # Instead of referencing image: nginx:mainline-alpine here, use build to
    # reference the current directory (.) and will look for a dockerfile by default
    build: .
    # The external directory location to map to an internal location
    volumes:
      - C:\Articles\NGINX-Content:/usr/share/nginx/html
    # The external port mapping to internal port mapping
    ports:
      - "80:80"
  node:
    image: node:current-alpine
    # Override the existing entrypoint to tell Node to execute the index.js file
    entrypoint: ['node','/usr/share/nginx/html/index.js']
    ports:
      - "3000:3000"
    # It is important that all containers can reference the same files
    volumes:
      - C:\Articles\NGINX-Content:/usr/share/nginx/html
  php:
    image: php:fpm-alpine
    ports:
      - "9000:9000"
    volumes:
      - C:\Articles\NGINX-Content:/usr/share/nginx/html
```

4\. Next, create the NGINX configuration file, _default.conf_, with the following. Notice the `proxy_pass` line. This line will pass the request to the `node` host.

```yaml
server {
    # The port to listen on
    listen 80;
    # The root directory should exactly match the internal volume share
    root /usr/share/nginx/html;

    # For all files with the PHP extension run the following to route to PHP-FPM
    location ~ ^/.+\.php(/|$) {
        # Pass the request to the host "php" and port 9000 (default PHP-FPM port)
        fastcgi_pass  php:9000;
		# Include the default NGINX FastCGI Parameters
        include       fastcgi_params;
		# Define one additional parameter telling PHP-FPM where to find the file
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    # For all files with the JS extension run the following to route to NodeJS
    location ~ ^/.+\.js(/|$) {
        # Pass the request to the host "node" and port 3000 (default NodeJS port)
        proxy_pass  http://node:3000;
    }
}
```

5\. Open a terminal and navigate to the _C:\\Articles\\NGINX-Both_ directory.

6\. Run the command, `docker-compose up` to generate and start your custom service as before.

![Starting the NGINX, PHP, and NodeJS containers via Docker Compose.](https://adamtheautomator.com/wp-content/uploads/2021/07/Untitled-2021-07-31T161736.129.png)

Starting the NGINX, PHP, and NodeJS containers via Docker Compose.

Next, create the file _index.js_ in the _C:\\Articles\\NGINX-Content_ directory and the file _index.php_ in that same directory, if it does not already exist, to test NGINX proxying both backends.

**index.js**

```javascript
// Assign the HTTP server object, built-in to NodeJS
var http = require('http');

// Create the server, on port 3000, and output the text content "Hello World!"
http.createServer(function (req, res) {
    res.write('Hello World!');
    res.end();
}).listen(3000, function(){
    console.log("server start at port 3000");
});
```

**index.php**

```php
<?php phpinfo(); ?>
```

8\. Finally, open a web browser and navigate to [http://localhost/index.js](http://localhost/index.js*) and [http://localhost/index.php](http://localhost/index.php*). You should now see that both are accessible, as shown below.

![Demonstrating that both the NodeJS and NGINX containers properly work.](https://adamtheautomator.com/wp-content/uploads/2021/07/Untitled-2021-07-31T162107.860.png)

Demonstrating that both the NodeJS and NGINX containers properly work.

## Conclusion

Now that you have successfully proxied both a PHP-FPM container and a NodeJS container, even at the same time, why not try load-balancing multiple NGINX containers?

Using an NGINX reverse proxy in Docker opens up a world of possibilities for properly segmenting applications and traffic among containers!

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fnginx-reverse-proxy-in-docker%2F&text=Create%20an%20NGINX%20Reverse%20Proxy%20in%20Docker%20and%20Learn%201%20New%20Skill!)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fnginx-reverse-proxy-in-docker%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fnginx-reverse-proxy-in-docker%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2021/07/Getting-Started-with-NGINX-on-Docker.jpg)

### [Provision NGINX on Docker and Increase Server Capabilities](/nginx-on-docker/)

learn how to provision a new NGINX Docker container running on any operating system such as Windows, macOS, or Linux!

![](https://adamtheautomator.com/wp-content/uploads/2026/02/featured_image-13.webp)

### [Azure Container Apps: Instant Preview Environments per PR](/build-ephemeral-preview-environments-every-pr/)

Build isolated preview environments for every pull request using Azure Container Apps revision labels and Azure DevOps pipelines with scale-to-zero economics.

![](https://adamtheautomator.com/wp-content/uploads/2025/11/55418e927e511ae263219c072e27d637c2a967a5036de7020b329582db775c26.png)

### [Automating Docker Container Health Checks with Python and Local Notifications](/docker-health-checks-python/)

Docker's built-in health checks are passive—they tell Docker when a container fails, but do they tell you? In this tutorial, we'll build a lightweight Python monitoring system that runs entirely on your infrastructure with zero external dependencies. You'll learn to detect container failures in real-time, send instant alerts, and maintain a complete audit log of every state change.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
