Install Lets Encrypt SSL Certificate using Docker, WordPress and DigitalOcean

In this article I am going to show you that how to install SSL Certificate on your wordpress website using Docker, Docker compose, Let’s Encrypt and Digital Ocean.

If you are interested in Video version of this article then you watch it from following youtube video:

I assume that you already have Docker and Docker compose installed and functional already.

To start you should create following folder structure:

In docker-compose.yaml file we will create three services:
1- WordPress
2- MySQL
3- Nginx ( letsencrypt image )

1- WordPress Service

Loading...

I added restart policy always. The benefit of this policy is that in case if your docker container stopped because of any error or crashed then it would automatically restart the container. That helps a lot because you don’t need to manually go to server and restart.

As this wordpress container depends on the mysql server because as you know that wordpress cannot work without a functional mysql server. So we should wait for the mysql service to be ready first before creating wordpress service. So to wait we added depends_on property.

stdin_open and tty are added to keep container alive forever.

In the volumes array I mounted our local src folder with the html container inside the container. So the benefit of this step is that if you remove the container then it would not delete the volumes that you have mounted. In this way you can persist your data without any loss.

You don’t need to expose any port for wordpress container because we are not going to access wordpress container directly. Its the nginx container that would forward our traffic to wordpress container’s port 80. I will show that later in this article.

in env_file array I added .env file path because wordpress image needs us to pass some environment variables as shown in the following screenshot:

Normally we use localhost as the database host name. But in this case mysql and wordpress will be installed in two different containers hence normally wordpress cannot access mysql on localhost host. But with the magic of docker-compose we can communicate any container from any container. We just need to use the name of server instead of localhost.

As we set the service name mysql for mysql server so that is why we would use mysql as host name through the environment variable WORDPRESS_DB_HOST

In other three variables, you need to add database username, password and database name. So make sure that in next steps you should use same names in mysql service.

2- MySQL service:

Loading...

I mounted two volumes. One is data folder to store all data files of mysql and second is my.cnf file so that I can easily change mysql settings in future if needed without going inside container.

Next you need to expose 3306 port and map it with your local 3306 port.

Just copy paste following my.cnf file:

Loading...

3- nginx Service

Loading...

Here I exposed port 80 and 443 and mapped it with the local port 80 and 443 respectively to receive traffic directly.

Then I mounted the volumes pass my configuration and persist the configurations and certificate related files.
In the property SUBDOMAINS you can add as many sub domains as you want by separating them with comma. You can check the official documentation of the linuxserver/letsencrypt image to see all available options. There are different validation methods. But the easiest method it by using http validation.

As the initial stage you should set the value of STAGING equal to true. Because for the first time you want to test if your all configurations are correct. Production certificate has rate limits. So you cannot create a lot of certificates within specific limit of time. So to avoid to reach the rate limit, you should first try staging that would then create fake certificate. After you see that fake certificate is live in your website then you are ready to change the value from staging=true to false to apply real production certificate.

Use following configuration file in your file structure:

nginx.conf

Loading...

There is only one important thing to note in above file that is proxy_pass value. I used proxy_pass http://wordpress:80;

In this value you need to provide the name of the service of wordpress that you mentioned in docker-compose.yaml

ssl.conf

Loading...

Now our files are ready to run.

Before that you should create a droplet on digital ocean. After your droplet is ready you will get an ip address like this:

Copy the ip address and change the A record of your domain name to set this ip address.

I linked my domain name server with digital ocean so I can change A record right from the digitalOcean domains section. But if you are managing domain name from other domain company then still procedure is same. let me show you screenshot of A record in digital ocean.

After A record is added then you are ready to continue.

First create folder /root/project/ in the droplet and copy all your files to the droplet. I used this command form the root of my project folder:

Loading...

You have to ssh into your container. I used this command to enter into this container but you can use password if this does not work for you:

Loading...

Now run this command:

Loading...

now wait and watch the progress.

Now open your domain name in the browser and you would see a warning message saying your connection is not private. This means that your fake certificate is installed.

As now your configurations worked fine so now you are ready to install production real ssl certificate. Before this you need to remove all existing certificate configurations from the docker/nginx/configs folder.

So run this command:

Loading...

run this command to shutdown all services:

Loading...

In docker-compose.yaml file change the value from STAGING=true to false

and then run again

Loading...

Now watch the progress and if you see congratulations message like before then you can refresh your page to see if ssl certificate is installed. It should show lock icon with green message:

As now everything working perfectly so now stop server by pressing command + c keys on your keyboard in terminal.

And then run services in detached mode by passing -d flag so that i can keep running forever in the background without any need to keep terminal open. you can then close terminal after running this command:

Loading...

Github source code: https://bit.ly/2MoaBWf

Youtube Video Link: https://www.youtube.com/watch?v=lbXc6mKh7U0&t=587s