Docker Wordpress Nginx



In this video we’ll take a look at installing WordPress on Docker! WordPress is open source software you can use to create a beautiful website, blog, or app. In order to setup a WordPress container on your Docker server, you’ll need a few additional things. To set up WordPress, you need a proper stack; it may be LAMP (Linux, Apache, MySQL, PHP) or LEMP (Linux, Nginx, MySQL, PHP). Installing all these components can be time-consuming, and you may not have the flexibility to play with your code. This is where Docker comes in. Docker uses containers to create, deploy, and run applications. Docker run -name docker-nginx -p 8080:80 nginx Pointing a browser on your network to the IP address of the host machine, at port 8080, will display the NGINX splash page. Running in detached mode.

NGINX is one of the most popular web servers in the world. Not only is NGINX a fast and reliable static web server, it is also used by a ton of developers as a reverse-proxy that sits in front of their APIs.

In this tutorial we will take a look at the NGINX Official Docker Image and how to use it. We’ll start by running a static web server locally then we’ll build a custom image to house our web server and the files it needs to serve. We’ll finish up by taking a look at creating a reverse-proxy server for a simple REST API and then how to share this image with your team.

Prerequisites

To complete this tutorial, you will need the following:

  • Free Docker Account
    • You can sign-up for a free Docker account and receive free unlimited public repositories
  • Docker running locally
  • An IDE or text editor to use for editing files. I would recommend VSCode

NGINX Official Image

The Docker Official Images are a curated set of Docker repositories hosted on Docker Hub that have been scanned for vulnerabilities and are maintained by Docker employees and upstream maintainers.

Official Images are a great place for new Docker users to start. These images have clear documentation, promote best practices, and are designed for the most common use cases.

Let’s take a look at the NGINX official image. Open your favorite browser and log into Docker. If you do not have a Docker account yet, you can create one for free.

Once you have logged into Docker, enter “NGINX” into the top search bar and press enter. The official NGINX image should be the first image in the search results. You will see the “OFFICIAL IMAGE” label in the top right corner of the search entry.

Now click on the nginx result to view the image details.

On the image details screen, you are able to view the description of the image and it’s readme. You can also see all the tags that are available by clicking on the “Tags” tab

Running a basic web server

Let’s run a basic web server using the official NGINX image. Run the following command to start the container.

With the above command, you started running the container as a daemon (-d) and published port 8080 on the host network. You also named the container web using the --name option.

Open your favorite browser and navigate to http://localhost:8080 You should see the following NGINX welcome page.

This is great but the purpose of running a web server is to serve our own custom html files and not the default NGINX welcome page.

Let’s stop the container and take a look at serving our own HTML files.

Adding Custom HTML

By default, Nginx looks in the /usr/share/nginx/html directory inside of the container for files to serve. We need to get our html files into this directory. A fairly simple way to do this is use a mounted volume. With mounted volumes, we are able to link a directory on our local machine and map that directory into our running container.

Let’s create a custom html page and then serve that using the nginx image.

Create a directory named site-content. In this directory add an index.html file and add the following html to it:

Now run the following command, which is the same command as above, but now we’ve added the -v flag to create a bind mount volume. This will mount our local directory ~/site-content locally into the running container at: /usr/share/nginx/html

Open your favorite browser and navigate to http://localhost:8080 and you should see the above html rendered in your browser window.

Build Custom NGINX Image

Bind mounts are a great option for running locally and sharing files into a running container. But what if we want to move this image around and have our html files moved with it?

There are a couple of options available but one of the most portable and simplest ways to do this is to copy our html files into the image by building a custom image.

To build a custom image, we’ll need to create a Dockerfile and add our commands to it.

In the same directory, create a file named Dockerfile and paste the below commands.

We start building our custom image by using a base image. On line 1, you can see we do this using the FROM command. This will pull the nginx:latest image to our local machine and then build our custom image on top of it.

Docker wordpress nginx

Next, we COPY our index.html file into the /usr/share/nginx/html directory inside the container overwriting the default index.html file provided by nginx:latest image.

You’ll notice that we did not add an ENTRYPOINT or a CMD to our Dockerfile. We will use the underlying ENTRYPOINT and CMD provided by the base NGINX image.

To build our image, run the following command:

The build command will tell Docker to execute the commands located in our Dockerfile. You will see a similar output in your terminal as below:

Now we can run our image in a container but this time we do not have to create a bind mount to include our html.

Open your browser and navigate to http://localhost:8080 to make sure our html page is being served correctly.

Setting up a reverse proxy server

A very common scenario for developers, is to run their REST APIs behind a reverse proxy. There are many reasons why you would want to do this but one of the main reasons is to run your API server on a different network or IP then your front-end application is on. You can then secure this network and only allow traffic from the reverse proxy server.

Nginx

For the sake of simplicity and space, I’ve created a simple frontend application in React.js and a simple backend API written in Node.js. Run the following command to pull the code from GitHub.

Once you’ve cloned the repo, open the project in your favorite IDE. Take a look at Dockerfile in the frontend directory.

The Dockerfile sets up a multi-stage build. We first build our React.js application and then we copy the nginx.conf file from our local machine into the image along with our static html and javascript files that were built in the first phase.

We configure the reverse proxy in the frontend/nginx/nginx.conf file. You can learn more about configuring Nginx in their documentation.

As you can see in the second location section thatall traffic targeted to /services/m will be proxy_pass to http://backend:8080/services/m

In the root of the project is a Docker Compose file that will start both our frontend and backend services. Let’s start up our application and test if the reverse proxy is working correctly.

You can see that our nginx web server has started and also our backend_1 service has started and is listening on port 8080.

Open your browser and navigate to http://localhost. You should see the following web page:

Open the developer tools window and click on the “network” tab. Now back in the browser, enter an entity name. This can be anything. I’m going to use “widgets”. Then click the “Submit” button.

Over in the developer tools window, click on the network request for widgets and see that the request was made to http://localhost and not to http://localhost:8080.

Open your terminal and notice that request that was made from the browser was proxied to the backend_1 service and handled correctly.

Shipping Our Image

Now let’s share our images on Docker so others on our team can pull the images and run them locally. This is also a great way to share your application with others outside of your team such as testers and business owners.

To push your images to Docker’s repository run the docker tag and then the docker push commands. You will first need to login with your Docker ID. If you do not have a free account, you can create one here.

Awesome Compose

The Awesome compose project is a curated list of Docker Compose samples. These samples provide a starting point for how to integrate different services using a Compose file and to manage their deployment with Docker Compose.

In the awesome compose repository you can find project templates that use NGINX as a static web server or a reverse proxy. Please take a look and if you do not find what you are looking for please consider contributing to the project. Checkout the Contribution Guide for more details.

Conclusion

In this article we walked through running the NGINX official image, adding our custom html files, building a custom image based off of the official image and configuring the NGINX as a reverse proxy. We finished up by pushing our custom image to Docker so we could share with others on our team.

If you have any questions, please feel free to reach out on Twitter @pmckee and join us in our community slack.

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 https://github.com/dawilk/coderevolve-docker-reverseproxy.git

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:
./sites-enabled/coderevolve-site.com.conf

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

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.
    • coderevolve-site.com | 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…

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!

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.

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:
127.0.0.1 coderevolve-site.com

Now you can access the WordPress site through the reverse proxy at http://coderevolve-site.com

Cleanup

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

Docker Wordpress Nginx Reverse Proxy

  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 coderevolve-site.com.conf 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 coderevolve-site.com.conf 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

Conclusion

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.

Docker Wordpress Nginx Ssl

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.

Docker Wordpress Nginx Github

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!