This guide will build on the foundation laid by WordPress in Docker.

In the previous guide, we used docker-compose to create a WordPress site.
In this guide, we’ll use docker-compose again to create a reverse proxy.
See alternative configurations at the bottom for adding TLS to the reverse proxy for the purpose of traffic encryption and SSL termination.

The Short Answer

Create and start a reverse proxy for your WordPress site from the previous post using these steps:

  1. Download templates for docker-compose and nginx
  2. Create a reverseproxy network:
    docker network create reverseproxy
  3. Update the WordPress docker-compose.yml and .env to support reverse proxy, and then restart it.
    These changes are already made for you on this branch of the WordPress project
  4. Start nginx:
    docker-compose up -d

That’s it! You’re now running the website behind a reverse proxy!

For a more detailed answer on these steps, read on!

The Long Answer

Before continuing, you should have Docker installed already. Links to installations for all operating systems can be found on the sidebar.

Step 1: Download templates for docker-compose and Nginx

You can get the latest revision of the templates from the GitHub repo.

git clone

This repo is designed to act as a portable web config. Once you’ve modified the templates to meet your needs, you could copy the whole folder from one system to the next to backup or duplicate the proxy.

Step 2: Create a reverseproxy network

We’re going to take port 80 away from the wordpress container and give it to our reverse proxy (nginx). But before we do this, we need to create a network that allows nginx to pass traffic to the wordpress container. This is where a new docker network comes into play.

We’ll create a docker network and call it “reverseproxy”:
docker network create reverseproxy

Step 3a: Understanding the nginx template

To get this going quickly we would only need to look at one file:

Below is the config for the fictional The items in bold are the things we would change if we weren’t doing

upstream coderevolve-upstream {
  server coderevolve-webhost:80;

server {
  listen        80;

  location / {
    proxy_pass http://coderevolve-upstream;

If you’re new to nginx configs, here is a quick breakdown of ours:

  • Sections
    • upstream | This defines a list of “targets” or “backends”. Our list has only one target.
    • server | This determines what port we bind, what domain(s) we handle, and how we handle certain traffic.
    • location | This sets the what and where of traffic handling. In our case, we send all traffic (captured by the /) to the upstream servers.
  • Settings
    • coderevolve-upstream | This can really be whatever you want. It should be unique for each application/site that nginx will proxy, however.
    • coderevolve-webhost | This will be the IP or resolvable hostname (or container_name) of the site. In our case, we have it set to match the WORDPRESS_WEB_HOST value from the .env file in the previous guide.
    • | This should be the domain name for the website. If you want to enable HTTPS later, this should be a domain name that you own!

Step 3b: Modify the WordPress config

Next, we have to make a few changes to the docker-compose.yml and .env files from the previous post. The changes below are required to make the wordpress container compatible with being an upstream for nginx.

Update the the WordPress docker-compose.yml

We change the top networks: section as follows…

# Before
    external: false

# After
    external: false
    external: true

This change tells this docker-compose service collection that it will use the new “reverseproxy” network that we just created.

We also make two changes to the wp: service section
Again, that’s the wp: section, NOT the wp-mysql: section!

# Before
       - wordpress-backend
       - 80:80

# After
       - wordpress-backend
       - reverseproxy
       - 80

This change will join the wordpress container to the reverseproxy docker network, and it will expose port 80 on the container only within docker networks. In other words, we just took the host machine port 80 binding from the wordpress container.

Update the .env file

Next, we need to change the URL for WordPress from http://localhost to match the domain for our site. We would change the bold below to match the domain we used for the server_name in the nginx config in Step 3a.

# Before

# After

Apply the changes to the WordPress container

To apply these changes to the container, run docker-compose up -d from the wordpress directory. This will recreate the coderevolve-webhost container.

Step 4: Start the proxy

From the nginx folder, use docker-compose up -d

IMPORTANT: If the upstream is misconfigured, or if nginx cannot confirm the availability of your application, the reverseproxy container will fail to start!
You can check the STATUS of your container using docker ps.
If the reverseproxy container’s status is stuck in a Restarting loop, check the logs using docker logs reverseproxy.
If you see this error:
[emerg] host not found in upstream
…then you missed something in Steps 2-4 above!

Step 5: Edit your hosts file

Since we’re using a fictitious domain name here, we need to add an entry to our hosts file so that our computer knows the website is on our own machine.

Add the following line to your hosts file:

Now you can access the WordPress site through the reverse proxy at


The nginx container is configured to store very few files (depending on the template you use).

  1. Stop and delete the container with docker-compose down
  2. Delete everything in the logs and cache folders
  3. Delete the reverseproxy docker network with docker network rm reverseproxy

Alternative Configurations

Add TLS encryption (with redirect from http to https)

  1. Replace the contents of with the contents of example/reverseproxy-ssl.conf
  2. Create a public and private certificate key pair (or use the existing self-signed set included, and skip to #5 below).
    Let’s Encrypt will provide a free certificate if you own the domain.
    Alternatively, you can use a tool like OpenSSL to create your own self-signed certificate.
  3. Place the two certificate files (certificate and key) in the ssl directory.
  4. Update the ssl_certificate and ssl_certificate_key lines in based on the certificate files’ names.
    NOTE: The path must start with /etc/nginx/ssl/ as shown in the example file. This is the where the ssl files are located in the container, NOT where they are located on your local machine.
  5. Restart the nginx container with docker-compose restart

Your site will now redirect to https, and encrypt traffic using your certificate.

Combine all three services in one docker-compose.yml

  1. Stop the reverseproxy container if it is running using docker-compose down.
  2. Copy the whole nginx service section from the nginx docker-compose.yml file over to the wordpress docker-compose.yml file.
  3. Set the reverseproxy network to external: false
  4. Copy nginx.conf, as well as the sites-enabled, ssl, and includes folders to the wordpress main folder.
  5. Run docker-compose up -d again in the wordpress folder to restart the containers with the merged configuration.

Some notes on combining the services into one docker-compose:

  • you don’t need the docker network create step from earlier in this guide
  • only one master folder to manage
  • only one command required to start and stop all containers
  • easier to manage when there are few services, but can get messy at larger scales


In this guide, we created a reverse proxy container to handle traffic to the WordPress website running in another container. With the alternative configurations, we effectively added TLS to the website with http to https redirect.

This reverse proxy is going to be a critical component in future guides as we want to serve more than one website or application using the same ports (80/443) on the same system.

However, before we start adding additional websites for nginx to proxy, we will first set up a certbot container to automate certificate creation and renewal for this website (and therefore, future websites). That will be in the next guide. Click here to continue!

Last modified: September 7, 2020