Install Nginx and Let’s Encrypt with Docker – Ubuntu 20.04

Create Docker Compose YML file

Now SSH inside your server or Virtual machine and create a directory to hold all the configurations by running the following command.
1
sudo mkdir ~/nginx-ssl
Copied!
Move inside the directory and create a docker-compose.yml file that holds our configuration.
1
cd ~/nginx-ssl
2
sudo nano ~/nginx-ssl/docker-compose.yml
Copied!
Paste the following configurations inside the file.
1
version: "3.8"
2
services:
3
web:
4
image: nginx:latest
5
restart: always
6
volumes:
7
- ./public:/var/www/html
8
- ./conf.d:/etc/nginx/conf.d
9
- ./certbot/conf:/etc/nginx/ssl
10
- ./certbot/data:/var/www/certbot
11
ports:
12
- 80:80
13
- 443:443
14
15
certbot:
16
image: certbot/certbot:latest
17
command: certonly --webroot --webroot-path=/var/www/certbot --email [email protected] --agree-tos --no-eff-email -d domain.com -d www.domain.com
18
volumes:
19
- ./certbot/conf:/etc/letsencrypt
20
- ./certbot/logs:/var/log/letsencrypt
21
- ./certbot/data:/var/www/certbot
Copied!
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.
  • image: We use latest Nginx and Certbot images available in Docker hub.
  • volumes:
    • public: 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.
    • certbot/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.
Now you have your docker-compose.yml in place.

Configure Nginx

Now we need to configure Nginx for validation to obtain the Let’s Encrypt SSL certificate.
We will create a directory as mentioned in the docker-compose file as conf.d.
1
sudo mkdir ~/nginx-ssl/conf.d
Copied!
Create a configuration file with the .conf extension.
1
sudo nano ~/nginx-ssl/conf.d/default.conf
Copied!
Paste the following configuration inside the file.
1
server {
2
listen [::]:80;
3
listen 80;
4
5
server_name domain.com www.domain.com;
6
7
location ~ /.well-known/acme-challenge {
8
allow all;
9
root /var/www/certbot;
10
}
11
}
Copied!
Hit CTRL-X followed by Y and ENTER to save and exit the file.
Now you have the Nginx configuration which gets synced to the /etc/nginx/conf.d folder which automatically gets loaded by Nginx.

Start Containers

Now it’s time to start the containers using the following command to receive the SSL certificates.
You need to pass the -d flag which starts the container in background and leaves them running.
1
docker-compose up -d
Copied!
You will see an output similar to the one below.
1
Output
2
Creating network "nginx-ssl_default" with the default driver
3
Pulling web (nginx:latest)…
4
latest: Pulling from library/nginx
5
8559a31e96f4: Pull complete
6
8d69e59170f7: Pull complete
7
3f9f1ec1d262: Pull complete
8
d1f5ff4f210d: Pull complete
9
1e22bfa8652e: Pull complete
10
Digest: sha256:21f32f6c08406306d822a0e6e8b7dc81f53f336570e852e25fbe1e3e3d0d0133
11
Status: Downloaded newer image for nginx:latest
12
Pulling certbot (certbot/certbot:latest)…
13
latest: Pulling from certbot/certbot
14
cbdbe7a5bc2a: Pull complete
15
26ebcd19a4e3: Pull complete
16
a29d43ca1bb4: Pull complete
17
979dbbcf63e0: Pull complete
18
30beed04940c: Pull complete
19
48a1f8a4d505: Pull complete
20
4416e9b4bbe0: Pull complete
21
8173b4be7870: Pull complete
22
21c8dd124dab: Pull complete
23
c19b04e11dc7: Pull complete
24
1b560611cec1: Pull complete
25
Digest: sha256:568b8ebd95641a365a433da4437460e69fb279f6c9a159321988d413c6cde0ba
26
Status: Downloaded newer image for certbot/certbot:latest
27
Creating nginx-ssl_certbot_1 … done
28
Creating nginx-ssl_web_1 … done
Copied!
This output indicates Nginx and Certbot images are pulled from Docker hub and the containers are created successfully.
To view the containers you can execute the following command.
1
docker-compose ps
Copied!
1
Output
2
Name Command State Ports
3
nginx-ssl_certbot_1 certbot certonly --webroot … Exit 0
4
nginx-ssl_web_1 /docker-entrypoint.sh ngin … Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
Copied!
The state Exit 0 indicates the setup is completed without any error.
Now when you check your work directory, there will be a new directory created as certbot inside which you will have the SSL certificate synced.
1
ls ~/nginx-ssl/certbot/conf/live/domain.com
Copied!

Configure SSL with Nginx

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.
Your file should like the one below at the final stage.
1
server {
2
listen [::]:80;
3
listen 80;
4
5
server_name domain.com www.domain.com;
6
7
location ~ /.well-known/acme-challenge {
8
allow all;
9
root /var/www/certbot;
10
}
11
12
# redirect http to https www
13
return 301 https://www.domain.com$request_uri;
14
}
15
16
server {
17
listen [::]:443 ssl http2;
18
listen 443 ssl http2;
19
20
server_name domain.com;
21
22
# SSL code
23
ssl_certificate /etc/nginx/ssl/live/domain.com/fullchain.pem;
24
ssl_certificate_key /etc/nginx/ssl/live/domain.com/privkey.pem;
25
26
root /var/www/html;
27
28
location / {
29
index index.html;
30
}
31
32
return 301 https://www.domain.com$request_uri;
33
}
34
35
server {
36
listen [::]:443 ssl http2;
37
listen 443 ssl http2;
38
39
server_name www.domain.com;
40
41
# SSL code
42
ssl_certificate /etc/nginx/ssl/live/domain.com/fullchain.pem;
43
ssl_certificate_key /etc/nginx/ssl/live/domain.com/privkey.pem;
44
45
root /var/www/html/domain-name/public;
46
47
location / {
48
index index.html;
49
}
50
}
Copied!
Hit CTRL-X followed by Y and ENTER to save and exit the file.

Create index.html file

Now you can create the index.html file inside the public directory which then syncs to the directory configured.
Create the public directory.
1
sudo mkdir ~/nginx-ssl/public
Copied!
1
sudo nano ~/nginx-ssl/public/index.html
Copied!
1
<html>
2
<body>
3
<h1>Docker setup with Nginx and Let's Encrypt SSL.</h1>
4
</body>
5
</html
Copied!
Hit CTRL-X followed by Y and ENTER to save and exit the file.

Restart the containers

Now you can restart the containers to load the new configurations.
1
docker-compose restart
Copied!
Once the containers are restarted you can check your domain name. You will get a redirection to HTTPS and your SSL.