Skip to content

Docker-compose with let's encrypt: TLS Challenge

This guide aim to demonstrate how to create a certificate with the let's encrypt TLS challenge to use https on a simple service exposed with Traefik.
Please also read the basic example for details on how to expose such a service.

Prerequisite

For the TLS challenge you will need:

  • A publicly accessible host allowing connections on port 443 with docker & docker-compose installed.
  • A DNS record with the domain you want to expose pointing to this host.

Setup

  • Create a docker-compose.yml on your remote server with the following content:
version: "3.3"

services:

  traefik:
    image: "traefik:v2.4"
    container_name: "traefik"
    command:
      #- "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      #- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.myresolver.acme.email=postmaster@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "443:443"
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "traefik/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.example.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=myresolver"
  • Replace [email protected] by your own email within the certificatesresolvers.myresolver.acme.email command line argument of the traefik service.
  • Replace whoami.example.com by your own domain within the traefik.http.routers.whoami.rule label of the whoami service.
  • Optionally uncomment the following lines if you want to test/debug:

    #- "--log.level=DEBUG"
    #- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
  • Run docker-compose up -d within the folder where you created the previous file.

  • Wait a bit and visit https://your_own_domain to confirm everything went fine.

Note

If you uncommented the acme.caserver line, you will get an SSL error, but if you display the certificate and see it was emitted by Fake LE Intermediate X1 then it means all is good. (It is the staging environment intermediate certificate used by let's encrypt). You can now safely comment the acme.caserver line, remove the letsencrypt/acme.json file and restart Traefik to issue a valid certificate.

Explanation

What changed between the basic example:

  • We replace the web entry point by one for the https traffic:
command:
  # Traefik will listen to incoming request on the port 443 (https)
  - "--entrypoints.websecure.address=:443"
ports:
  - "443:443"
  • We configure the Https let's encrypt challenge:
command:
  # Enable a tls challenge named "myresolver"
  - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
  • We add a volume to store our certificates:
volumes:
  # Create a letsencrypt dir within the folder where the docker-compose file is
  - "./letsencrypt:/letsencrypt"

command:
  # Tell to store the certificate on a path under our volume
  - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
  • We configure the whoami service to tell Traefik to use the certificate resolver named myresolver we just configured:
labels:
  # Uses the Host rule to define which certificate to issue
  - "traefik.http.routers.whoami.tls.certresolver=myresolver"