In a previous article, I discussed how to deploy a website to Windows/Linux using React, WordPress, and NGINX containers with Docker Compose. To do this, it is necessary that Docker containers to can speak to each other via the Docker network. A practical example of this, as per my referenced article, is how NGINX receives incoming client requests and communicates with the WordPress container to service those requests. This concept is known as a reverse proxying.
Docker Networking
Here is an stripped, example of a docker-compose.yml file that creates both an NGINX and WordPress container (simplified to relevant information only):
version: "3.2"
services:
wordpress:
image: wordpress:5.3.2-fpm-alpine
container_name: wordpress-cont
restart: unless-stopped
networks:
- app-network
nginx:
build:
context: ./web_server
dockerfile: Dockerfile
args:
react_dir: ${REACT_PROJECT_DIR:-reactapp}
container_name: nginx-cont
depends_on:
- wordpress
networks:
- app-network
networks:
app-network
We create two services: wordpress and nginx. I explicitly set the name of the Docker network to build which corresponds to this orchestration, called app-network (no functional purpose, in this case). Now, what I do not explicitly set is the address range of the network or the private IP addresses of each service — although I very much could.
I avoid explicitly setting the IP addresses of the service containers primarily because it doesn’t matter to me and I wouldn’t consider it as a best practice. If I wanted to change the address range at a later date, I can avoid having to adjust hardcoded private IP address references unique to that address range all over my application. I don’t want to reference 172.16.0.1 when I can very easily just reference the name of the service — like wordpress.
This is possible because when we run docker-compose up and execute our docker-compose.yml file, Docker Compose will assign an IP address to each container and assign the hostname of that container with the given service name specified in our docker-compose.yml file — so wordpress and nginx in our case.
NGINX Reverse Proxying
Here is an excerpt of an example nginx.conf file (NGINX configuration) which will receive requests and forward those requests to our WordPress service:
http {
server {
listen 80;
listen [::]:80;
...
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass wordpress:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
} ... }
}
Notice the bold-ed wordpress value in the fastcgi_pass (fastcgi_pass is basically the PHP equivalent to the regular proxy_pass directive). Since we are using Docker Compose to deploy both NGINX and WordPress, because of the supplementary Docker network that is created, NGINX is able to reference the WordPress service by name, with wordpress. NGINX receives the request, reverse proxies to the wordpress container to fulfill the request, then NGINX sends the data back to the requester as if it came from itself.
There you have it. A simple example of NGINX reverse proxying to containers using Docker Compose.