Getting a Free SSL Certificate in Docker with Let's Encrypt

Run Certbot in Docker and use the DNS-01 challenge to get a free Let's Encrypt TLS certificate — no port 80 required.

What are Let's Encrypt and Certbot

Let's Encrypt is a free, non-profit Certificate Authority that provides X.509 certificates for TLS encryption. It uses the ACME protocol to automatically verify domain ownership before issuing a certificate.

Certbot is the official command-line tool for managing Let's Encrypt certificates. We'll run it inside a Docker container — no installation required on the host.

Prerequisites

Before you start, make sure you have:

  • [x] A domain name with access to the DNS control panel
  • [x] Docker installed on the server
  • [x] Shell administrator access (sudo)
Unlike the HTTP-01 challenge, the DNS-01 challenge does not require ports 80 or 443 to be open. You only need to add a TXT record in your DNS provider.

Run Certbot in Docker

Use the following command to start Certbot and request a certificate. Replace auth.yourdomain.com with your actual subdomain and ~/letsencrypt with your preferred output folder:

sudo docker run -it --rm \
  -v ~/letsencrypt:/etc/letsencrypt \
  certbot/certbot \
  certonly -d auth.yourdomain.com --manual --preferred-challenges dns

This command: - Starts a temporary, interactive Certbot container (-it --rm) - Mounts ~/letsencrypt as the certificate output directory - Requests a certificate using the DNS-01 challenge in manual mode

Certbot will first ask for your email address and acceptance of the Terms of Service, then output a challenge value.

Add the DNS TXT record

Certbot will print a challenge that looks like this:

Please deploy a DNS TXT record under the name:
_acme-challenge.auth.yourdomain.com.
with the following value:
4dh7sSh67DFlkgRmB_i_n74CkShgdDz7-kjhe98ko3s

Before continuing, verify the TXT record has been deployed.
Press Enter to Continue

Go to your DNS provider and add the record:

Name Type TTL Value
_acme-challenge.auth TXT 300 4dh7sSh67DFlkgRmB_i_n74CkShgdDz7-kjhe98ko3s

Wait for the record to propagate before pressing Enter. You can verify with Google Admin Toolbox — look for the value in the ;ANSWER section.

Certificate output

Once validation passes, Certbot prints the file locations:

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/auth.yourdomain.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/auth.yourdomain.com/privkey.pem
This certificate expires on 2024-03-25.

On your host machine those files are under ~/letsencrypt/live/auth.yourdomain.com/. The directory structure Certbot creates is:

~/letsencrypt/
├── archive/
│   └── auth.yourdomain.com/
│       ├── cert1.pem
│       ├── chain1.pem
│       ├── fullchain1.pem
│       └── privkey1.pem
└── live/
    └── auth.yourdomain.com/
        ├── cert.pem       -> ../../archive/.../cert1.pem
        ├── chain.pem      -> ../../archive/.../chain1.pem
        ├── fullchain.pem  -> ../../archive/.../fullchain1.pem
        └── privkey.pem    -> ../../archive/.../privkey1.pem

Mount the live/ files as volumes into any container that needs TLS — nginx, Caddy, or any other service.

The certificate is valid for 90 days. To renew, repeat the same docker run command before expiry and update the DNS TXT record with the new challenge value.