Docker-compose with let's encrypt: DNS Challenge

本指南旨在演示如何通过让我们加密DNS挑战来创建证书,以便在Traefik公开的简单服务上使用https.
请同时阅读基本示例,以获取有关如何公开此类服务的详细信息.

Prerequisite

对于DNS挑战,您需要:

  • 正常工作的提供商以及允许创建和删除DNS记录的凭据.

变量可能会有所不同,具体取决于提供程序.

请注意,本指南可能会因您使用的提供商而异. 唯一改变的是您将需要定义的变量名称,以便配置您的提供程序,以便它可以创建DNS记录.
请参考上面给出的提供程序列表,并用本文档中描述的所有环境变量替换所有环境变量.

Setup

  • 创建具有以下内容docker-compose.yml文件:
version: "3.3"

services:

  traefik:
    image: "traefik:v2.0.0-rc3"
    container_name: "traefik"
    command:
      #- "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
      - "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
      #- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "[email protected]omain.com"
      - "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    environment:
      - "OVH_ENDPOINT=xxx"
      - "OVH_APPLICATION_KEY=xxx"
      - "OVH_APPLICATION_SECRET=xxx"
      - "OVH_CONSUMER_KEY=xxx"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "containous/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=mydnschallenge"
  • 自己替换环境变量:

    environment:
      - "OVH_ENDPOINT=[YOUR_OWN_VALUE]"
      - "OVH_APPLICATION_KEY=[YOUR_OWN_VALUE]"
      - "OVH_APPLICATION_SECRET=[YOUR_OWN_VALUE]"
      - "OVH_CONSUMER_KEY=[YOUR_OWN_VALUE]"
  • traefik服务的certificatesresolvers.mydnschallenge.acme.email命令行参数中,用您自己的电子邮件替换[email protected] .

  • whoami服务的traefik.http.routers.whoami.rule标签中,用您自己的域替换whoami.mydomain.com .
  • (可选)如果要测试/调试,请取消注释以下几行:

    #- "--log.level=DEBUG"
    #- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
  • 在创建前一个文件的文件夹中运行docker-compose up -d .

  • 请稍等片刻,然后访问https://your_own_domain以确认一切正常.

Note

如果取消注释acme.caserver行,则会收到SSL错误,但是如果显示证书并看到它是由Fake LE Intermediate X1发出的,则表示一切都很好. (这是让我们加密使用的暂存环境中间证书). 现在,您可以安全地注释acme.caserver行,删除letsencrypt/acme.json文件,然后重新启动Traefik以颁发有效证书.

Explanation

初始设置之间发生了什么变化:

  • 我们为https流量配置第二个入口点:
command:
  # Traefik will listen to incoming request on the port 443 (https)
  - "--entrypoints.websecure.address=:443"
ports:
  - "443:443"
  • 我们配置DNS,让我们加密挑战:
command:
  # Enable a dns challenge named "mydnschallenge"
  - "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
  # Tell which provider to use
  - "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
  # The email to provide to let's encrypt
  - "[email protected]omain.com"
  • 我们通过环境变量向我们的提供程序提供所需的配置:
environment:
  - "OVH_ENDPOINT=xxx"
  - "OVH_APPLICATION_KEY=xxx"
  - "OVH_APPLICATION_SECRET=xxx"
  - "OVH_CONSUMER_KEY=xxx"

Note

此步骤可能会有所不同,具体取决于您使用的提供程序. 只需定义您的提供程序所需的变量即可. (请参阅清单的前提条件)

  • 我们添加一个卷来存储我们的证书:
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.mydnschallenge.acme.storage=/letsencrypt/acme.json"
  • 我们配置whoami服务,以告知Traefik使用我们刚刚配置的名为mydnschallenge的证书解析器:
labels:
    - "traefik.http.routers.whoami.tls.certresolver=mydnschallenge" # Uses the Host rule to define which certificate to issue

Use Secrets

要配置提供程序,并避免在docker-compose环境部分中以纯文本形式公开秘密,可以使用docker秘密.
关键是要通过另一种方式管理这些秘密文件,并从docker-compose.yml文件中读取它们,从而使docker-compose.yml -compose文件本身不那么敏感.

  • 创建一个名为secrets的目录,并为配置提供程序所需的每个参数创建一个文件,其中包含该参数的值:
    例如, ovh_endpoint.secret文件包含ovh-eu
./secrets
├── ovh_application_key.secret
├── ovh_application_secret.secret
├── ovh_consumer_key.secret
└── ovh_endpoint.secret

Note

您可以将这些机密存储在服务器上的任何位置,只需确保为docker-compose.yml文件中的机密定义使用file指令的正确路径.

  • 使用此docker-compose.yml文件:
version: "3.3"

secrets:
  ovh_endpoint:
    file: "./secrets/ovh_endpoint.secret"
  ovh_application_key:
    file: "./secrets/ovh_application_key.secret"
  ovh_application_secret:
    file: "./secrets/ovh_application_secret.secret"
  ovh_consumer_key:
    file: "./secrets/ovh_consumer_key.secret"

services:

  traefik:
    image: "traefik:v2.0.0-rc3"
    container_name: "traefik"
    command:
      #- "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
      - "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
      #- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "[email protected]omain.com"
      - "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    secrets:
      - "ovh_endpoint"
      - "ovh_application_key"
      - "ovh_application_secret"
      - "ovh_consumer_key"
    environment:
      - "OVH_ENDPOINT_FILE=/run/secrets/ovh_endpoint"
      - "OVH_APPLICATION_KEY_FILE=/run/secrets/ovh_application_key"
      - "OVH_APPLICATION_SECRET_FILE=/run/secrets/ovh_application_secret"
      - "OVH_CONSUMER_KEY_FILE=/run/secrets/ovh_consumer_key"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "containous/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=mydnschallenge"

Note

仍然考虑whoami.mydomain.com您自己的值更改[email protected]whoami.mydomain.com .

让我们解释一下我们刚刚做了什么:

  • 以下部分允许读取Docker主机上的文件,并在容器内的/run/secrets/[NAME_OF_THE_SECRET]下公开这些文件:
secrets:
  # secret name also used to name the file exposed within the container
  ovh_endpoint:
     # path on the host
    file: "./secrets/ovh_endpoint.secret"
  ovh_application_key:
    file: "./secrets/ovh_application_key.secret"
  ovh_application_secret:
    file: "./secrets/ovh_application_secret.secret"
  ovh_consumer_key:
    file: "./secrets/ovh_consumer_key.secret"

services:
  traefik:
    # expose the predefined secret to the container by name
    secrets:
      - "ovh_endpoint"
      - "ovh_application_key"
      - "ovh_application_secret"
      - "ovh_consumer_key"
  • whoami服务中的环境变量带有_FILE后缀,这使我们可以指向包含该值的文件,而不是公开该值本身.
    acme客户端将读取那些文件的内容以获得所需的配置值.
environment:
  # expose the path to file provided by docker containing the value we want for OVH_ENDPOINT.
  - "OVH_ENDPOINT_FILE=/run/secrets/ovh_endpoint"
  - "OVH_APPLICATION_KEY_FILE=/run/secrets/ovh_application_key"
  - "OVH_APPLICATION_SECRET_FILE=/run/secrets/ovh_application_secret"
  - "OVH_CONSUMER_KEY_FILE=/run/secrets/ovh_consumer_key"