Install WordPress with Docker Nginx Reverse Proxy to Apache with SSL – Google Cloud. In this guide you are going to learn how to make a best performance setup with Docker, Docker Compose, Nginx, Apache, PHP7.4 and Let’s Encrypt to run WordPress on Ubuntu 20.04.
For WordPress database we will use a high performance external database server provided by Google (Cloud SQL).
This setup is tested on Google Cloud Platform with a Compute Engine with a 1.75 GB RAM Machine running Ubuntu 20.04 boot image and a Cloud SQL instance with MySQL 5.7.
You can also make this setup in any cloud services like AWS or Azure or DigitalOcean or any dedicated servers.
Prerequisites
- Running Compute Engine, see the Setting up Compute Engine Instance.
- Follow this guide to Install Docker on Ubuntu 20.04.
- For managing containers install Docker Compose on your server.
- A n external database server, see how to set up Cloud SQL in Google Cloud.
- Configure DNS to point the domain to the server to install SSL.
Once you have all the prerequisites done you can proceed to make the setup and configure WordPress.
Create Docker Compose YML File
SSH inside your server and start by creating a docker-compose.yml
file.
sudo nano docker-compose.yml
Copy the entire contents below and paste it in the file.
Make sure to replace the below mentioned environment variables.
version: "3.8"
services:
wordpress:
container_name: wordpress
image: wordpress:php7.4-apache
restart: always
stdin_open: true
tty: true
environment:
WORDPRESS_DB_HOST: CLOUDSQL_IP
WORDPRESS_DB_USER: database_user
WORDPRESS_DB_PASSWORD: database_user_password
WORDPRESS_DB_NAME: database_name
volumes:
- ./wordpress:/var/www/html
nginx:
container_name: nginx
image: nginx:latest
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./certbot/conf:/etc/nginx/ssl
- ./certbot/data:/var/www/html
certbot:
container_name: certbot
image: certbot/certbot:latest
command: certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email -d domain.com -d www.domain.com
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/logs:/var/log/letsencrypt
- ./certbot/data:/var/www/html
Hit CTRL-X
followed by Y
and ENTER
to save and exit the file.
Here are the configuration details.
- version: Compose file version which is compatible with the Docker Engine. You can check compatibility here.
- services: here we have 3 services named
wordpress
,nginx
andcertbot
. - image: We use latest WordPress with PHP7.4, Apache, Nginx and Certbot images available in Docker hub.
- volumes:
wordpress
: we have configured this directory to be synced with the directory we wish to use as the web root inside the container.conf.d
: here we will place the Nginx configuration file to be synced with the default Nginx conf.d folder inside the container.cedtbot/conf
: this is where we will receive the SSL certificate and this will be synced with the folder we wish to inside the container.ports
: configure the container to listen upon the listed ports.command
: the command used to receive the SSL certificate.
- environment: here we list all the environment variables that are available for the WordPress image.
CLOUDSQL_IP
: Replace it with your external database IP address.database_user
: Replace it with your database user namedatabase_user_password
: Replace it with your database user password.database_name
: Replace it with your database name.
Configure Nginx
As per the docker-compose.yml
configuration we need to create the default.conf
file inside the nginx/conf
directory.
Create the directory besides your docker-compose.yml
file to hold the configuration file.
sudo mkdir -p nginx/conf
Create a file named default.conf
.
sudo nano nginx/conf/default.conf
Place the following configurations, here we use reverse proxy configuration to wordpress container running Apache.
server {
listen [::]:80;
listen 80;
server_name domain.com www.domain.com;
root /var/www/html;
index index.php;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
try_files $uri @apache;
}
location ~ ^/\.user\.ini {
deny all;
}
location ~* \.(svg|svgz)$ {
types {}
default_type image/svg+xml;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location @apache {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_pass http://wordpress:80;
}
location ~[^?]*/$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_pass http://wordpress:80;
}
location ~ \.php$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_pass http://wordpress:80;
}
location ~/\. {
deny all;
access_log off;
log_not_found off;
}
}
Hit CTRL-X
followed by Y
and ENTER
to save and exit the file.
Now you have your docker compose configuration and your Nginx configuration.
Start Containers
Start the containers using the following command, you will receive the SSL certificates once the containers are started.
docker-compose up -d
Once all containers are started you will see two additional directories certbot
and wordpress
created alongside your docker-compose.yml
file.
The directory wordpress
holds all your WordPress website source code.
The directory certbot
holds all the files related to your SSL certificates.
To view the containers you can execute the following command.
docker-compose ps
Configure Let’s Encrypt SSL
As you have received the Let’s Encrypt SSL certificate you can configure HTTPS and setup redirection to HTTPS.
Edit the default.conf
and make the following changes.
sudo nano nginx/conf/default.conf
server {
listen [::]:80;
listen 80;
server_name domain.com www.domain;
return 301 https://www.domain.com$request_uri;
}
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name domain.com;
ssl_certificate /etc/nginx/ssl/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/live/domain.com/privkey.pem;
return 301 https://www.domain.com$request_uri;
}
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name www.domain.com;
ssl_certificate /etc/nginx/ssl/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/live/domain.com/privkey.pem;
root /var/www/html;
index index.php;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
try_files $uri @apache;
}
location ~ ^/\.user\.ini {
deny all;
}
location ~* \.(svg|svgz)$ {
types {}
default_type image/svg+xml;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location @apache {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_pass http://wordpress:80;
}
location ~[^?]*/$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_pass http://wordpress:80;
}
location ~ \.php$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_pass http://wordpress:80;
}
location ~/\. {
deny all;
access_log off;
log_not_found off;
}
}
Hit CTRL-X
followed by Y
and ENTER
to save and exit the file.
Now restart the Nginx service to load the new configurations.
docker-compose restart nginx
Now you can check your domain name. You will get a redirection to HTTPS and you will see the WordPress installation page to complete the installation.
Learn the most Advanced Techniques of WordPress with this easy to learn course now.
Conclusion
Now you have learned how to install and setup WordPress with Nginx, Apache, PHP 7.4 and Let’s Encrypt with Docker on Ubuntu 20.04.
Thanks for your time. If you face any problem or any feedback, please leave a comment below.
Under Site Health Status I get:
The REST API request failed due to an error.
Error: cURL error 7: Failed to connect to mydomain port 443: Connection refused (http_request_failed)
Thanks
Hello guys!
Well, first of all I would like to say that your website has become a reference for me.
Thank you very much for sharing so didactically valuable and updated information. They are generous!
But, I have a beginner’s question:
I even understand why port 80 conflicts with Apache and Nginx, but normally I stop port 80 from Apache or Nginx. Do you have any other solution, say that you have “good technical practice”?
Thank you!
André
Hi Andre,
Thank you for using Cloudbooklet. While you use Docker containers for Nginx and Apache the port 80 wont get any conflict because they the two web servers are in separate containers and they both can be accessible using port 80. If you dont use container setup then you will face the conflict.