SSL Certificate Authority for Docker and Traefik

This post documents how to get https working on your local Docker development environment using Traefik as a reverse proxy for multiple services.

Step 1 - Root SSL Certificate

Create a sub directory to store generated keys, certificates and related files in your home folder, for example .ssl.

Using OpenSSL, generate the private key file, rootCA.key.

For Windows, use Cygwin, Git Bash, PowerShell or other Unix-like CLI.

mkdir .ssl
cd .ssl

openssl genrsa -des3 -out rootCA.key 2048

This root certificate can be used to sign any number of certificates you may need to generate for individual domains.

Using the key, create a new root SSL certificate file named rootCA.cer. This certificate will be valid for 10 years (3650 days).

openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.cer

Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Random
Locality Name (eg, city) []:Random
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Random
Organizational Unit Name (eg, section) []:Random
Common Name (e.g. server FQDN or YOUR name) []:Local Certificate
Email Address []:example@domain.com

If you need a .pem file, simply copy and rename the generated certificate file. For example, cp rootCA.key rootCA.pem

Import The Root Certificate

The host system needs to have the root certificate imported and set as trusted so all individual certificates issued by it are also trusted.

Windows

Run Win + R and enter mmc to open the Microsoft Management Console.

Then select File, Add/Remove Snap-ins.

Select Certificates from the available snap-ins and press the Add button.

From the Certificates Snap-in dialog, select Computer account > Local Computer (the computer this console is running on), and press the Finish button to close the window.

Then press the OK button in the Add or Remove Snap-in window.

Select Certificates (Local Computer) and right-click Trusted Root Certification Authorities > All Tasks > Import to open the Certificate Import Wizard dialog. Browse for the rootCA.cer digital certificate file. e.g., ~/.ssl/rootCA.cer

Select Next to place the certificate in The Trusted Root Certification Authorities store.

Windows 10 Certificate Import Wizard - place the certificate in The Trusted Root Certification Authorities store
Windows 10 Certificate Import Wizard dialog

Then select Finish to close the dialog.

OS X

Double-click the rootCA.cer to open it in Keychain Access.

The rootCA.cer certificate appears in the Login Keychain.

Change the Keychain dropdown to System.

OS X Add Certificates dialog - Keychain: System
OS X Add Certificates, Keychain: System

Unlock the System Keychain, Open the Local Certificate, expand Trust

Change the When using this certificate: dropdown to Always Trust.

OS X Local Certificate - Always Trust
OS X Local Certificate, Always Trust

Step 2 - Domain SSL Certificate

Create a sub directory in the .ssl folder for the local.docker.whoami.com domain certificate.

cd .ssl
mkdir local.docker.whoami.com

These steps are performed in the local.docker.whoami.com folder.

cd local.docker.whoami.com

Create an OpenSSL configuration file named server.csr.cnf.

server.csr.cnf
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C=US
ST=RandomState
L=RandomCity
O=RandomOrganization
OU=RandomOrganizationUnit
emailAddress=noreply@local.docker.whoami.com
CN = local.docker.whoami.com

Create a v3.ext file for the X509 v3 certificate.

v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = local.docker.whoami.com

Create a certificate key named server.key for the local.docker.whoami.com domain using the configuration settings stored in the server.csr.cnf.

openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key -config <( cat server.csr.cnf )
Cygwin openssl generate rsa private key console output
openssl generate rsa private key

Certificate signing request is issued using the root SSL certificate to create a local.docker.whoami.com domain certificate. The output is a server.crt certificate file.

openssl x509 -req -in server.csr -CA ../rootCA.cer -CAkey ../rootCA.key -CAcreateserial -out server.crt -days 730 -sha256 -extfile v3.ext
Cygwin openssl certificate signing request console output
openssl certificate signing request

Browser - Root Certificate Import

Import the root CA certificate into the web browser trusted root certificate store.

Chrome: Settings (chrome://settings/) > Privacy and security, Manage certificates > Import, follow prompts to Browse for .ssl/rootCA.cer. In The Import Wizard Dialog | Certificate Store, Choose Automatically select the certificate store based on the type of certificate.

Firefox: Options > Privacy & Security, Certificates | View Certificates, Authorities > Import. Browse for the .ssl/rootCA.cer and select all 3 Trust checkboxes.

Traefik

Create a traefik project folder with a certs sub directory.

mkdir -p ~/traefik/certs  

Copy the domain certificate and key in the local.docker.whoami.com folder into the traefik/certs folder and rename them to match the respective domain. For example,

cd local.docker.whoami.com
cp server.crt ~/traefik/certs/local.docker.whoami.com.crt
cp server.key ~/traefik/certs/local.docker.whoami.com.key

In the traefik project folder, create this traefik.toml file.

traefik.toml
defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.http]
  address = ":80"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      certFile = "/etc/traefik/certs/local.docker.whoami.com.crt"
      keyFile = "/etc/traefik/certs/local.docker.whoami.com.key"

In in the traefik project folder, create this docker-compose.yml file to configure Traefik services and networks.

docker-compose.yml
version: "3"

services:
  proxy:
    image: traefik:v1.7
    restart: unless-stopped
    command: --docker --logLevel=DEBUG
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./certs:/etc/traefik/certs
      - ./traefik.toml:/etc/traefik/traefik.toml

networks:
  default:
    external:
      name: webgateway

update: note that we’re pulling a traefik version 1 image in the docker-compose.yml above. The traefik:latest image switched to version 2 in September 2019. A configuration migration guide can be found here should you want to use version 2.

Create this docker-compose.yml file in the whoami project folder.

docker-compose.yml
version: "3"

services:
  app:
    image: emilevauge/whoami
    networks:
      - web
    labels:
      - "traefik.backend=whoami"
      - "traefik.frontend.rule=Host:local.docker.whoami.com"

networks:
  web:
    external:
      name: webgateway

Hosts

Add 127.0.0.1 local.docker.whoami.com to your computers hosts file

Docker

Create a network named webgateway.

docker network create webgateway

Bring up the traefik container followed by the whoami container using docker-compose. For example,

cd ~/traefik
docker-compose up -d

cd ~/whoami
docker-compose up -d

Navigate to https://local.docker.whoami.com in a browser that has imported the root CA certificate into its trusted root store.

local.docker.whoami.com loaded on secure port 443 in Chrome

Linux Resources

comments powered by Disqus