Cloudflare + Docker Nginx & WordPress HTTPS

3 minutes, 28 seconds Read

For the past few days, I’ve been converting a site from Django to WordPress. 

For various reasons, I needed to use Nginx which means avoiding the standard WordPress Docker image which comes with Apache.

Services Required

  • Cloudflare – this will manage your HTTPS – turn on HTTPS in the settings in Flexible mode. Cloudflare’s flexible ssl means the connection between Coudflare and your server is always over http.
  • Nginx – you’re going to install Nginx from the latest image and copy in a standard Nginx config file from a build directory. The configuration should have the site listening on port 80. Cloudflare will manage the HTTPS for you.
  • WordPress FPM – this image uses the FastCGI implementation of PHP and in benchmarks is quicker than the standard Apache and PHP bundle. 
  • Database – use whatever database you prefer – I went with MariaDB – this configuration is outside this guide – there are hundreds of articles on how to get this set up. 

I was hosting a few different services and had a single docker-compose.yml file for the services. 

Nginx

  nginx:
    container_name: nginx
    build:
      context: nginx/
      dockerfile: Dockerfile
    restart: always
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - wordpress-fpm
    networks:
      - nginx_nw
    volumes:
      - static_volume:/site/static
      - wp_data:/var/www/html

It was important for me that I used the latest nginx image to keep onto of any vulnerabilities. You’ll note that I have a custom Dockerfile

Nginx Dockerfile

FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

The above simple Dockerfile copies the nginx.conf file to the /etc/nginx folder of the Docker container to host the site.

Nginx Config

I ran into a lot of problems with the Nginx configuration, particularly with the encryption and HTTPs. The complexing factor here was the Cloudflare encryption – I was getting very confused about where the encryption was ending and which ports should have been opened.

The most important factor I found was configuring nginx to listen on port 80, not 443. This will allow Cloudflare to handle the HTTPS and avoids having the complexity of Ngnix/Letsencrypt handling the SSL and Certificates.

I ended up with a configuration similar to the below:

server {
    listen 80 http2;
    server_name site.com;
    index index.php index.html index.htm;
    root /var/www/html;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # pass the PHP scripts to FastCGI server listening on wordpress-fpm:9000
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass wordpress-fpm:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    }

Note that the PHP file requests are passed off to the WordPress-FPM image, which is listening on port 9000. Let’s take a look at that now..

WordPress Docker Compose

There are two types of docker images for WordPress – the latest and default uses the php base image and installs Apache and WordPress into the image – therefore, you only need a database to get a site up and running. I didn’t want to use Nginx as a reverse proxy for Apache, so chose the second image, WordPress FPM.

WordPress FPM uses the FastCGI implementation for PHP and does not come bundled with a web server. According to some reports I read, WordPressFPM is faster than using the standard image.

WordPress FPM Docker Compose


  wordpress-fpm:
    container_name: wordoress-fpm
    build:
      context: build/
      dockerfile: Dockerfile
    volumes:
      - wp_data:/var/www/html
      - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    restart: always
    environment:
      - WORDPRESS_DB_HOST=
      - WORDPRESS_DB_USER=
      - WORDPRESS_DB_PASSWORD=
      - WORDPRESS_DB_NAME=

    networks:
      - nginx_nw
      - web_nw
    expose:
      - 9000

You’ll see from this configuration, we’re also using a Dockerfile for some settings. This Dockerfile is optional, but I used it to install the PHP-Redis extension. A future blog post will cover the use of Redis for caching.

FROM wordpress:fpm
RUN pecl install redis && docker-php-ext-enable redis

You’ll see the code above installs redid and the php extension required to get redis caching enabled. More to come on this.

Similar Posts