ngx_mrubyを使って最初のHTTPSアクセス時に自動で証明書を設定可能にするnginx-fastcertificateのdockerコンテナを作った

  • 2
    いいね
  • 0
    コメント

matsumoto-rさんのngx_mrubyで最初のHTTPSアクセス時に自動で証明書を設定可能にするFastCertificateの提案とPoCを参考に、Let's EncryptからSSL証明書を自動取得する仕組みを内包した nginx-fastcertificate を実現するDockerコンテナとdocker-compose設定例を作ってみました。

全体像

image

使い方

以下のような yaml ファイルを用意します。

docker-compose.yml
version: '3'
services:
  nginx:
    image: quay.io/akiray03/nginx-fastcertificate
    ports:
      - '80:80'
      - '443:443'
    volumes:
      - ./logs:/usr/local/nginx/logs
    links:
      - redis:redis
    environment:
      NGINX_WORKER_PROCESSES: 2
      REDIS_HOST: "redis"
      RESOLVER_ADDRESS: 8.8.8.8

      # ホストのプライベートIPアドレスを指定する or CLOUD_PROVIDER を指定する
      CLOUD_PROVIDER: Amazon # or Google
      # INTERNAL_IP: 192.168.0.10

      # このサーバで終端するドメイン名を半角スペース区切りで指定
      SSL_DOMAINS: "test.example.com test2.example.com"

      # ドメインごとに接続先情報を記述します (test.example.com の接続先)
      test_example_com_PROXY_TO_HOST: INTERNAL_IP
      test_example_com_PROXY_TO_PORT: '3000'
      # test2.example.com のリバースプロキシ接続先
      test2_example_com_PROXY_TO_URL: "https://test2.original.example.com/"
    depends_on:
      - redis

  redis:
    image: redis:3.2-alpine
    expose:
      - '6379'

そして、以下のコマンドを実行することで、SSL証明書の自動取得が行われるnginxが起動します。

$ docker-compose up

環境変数の説明

項目 説明
SSL_DOMAINS サーバで終端するドメイン名を半角スペース区切りで指定します
test_example_com_PROXY_TO_HOST リバースプロキシ接続先のIPアドレスを指定します
test_example_com_PROXY_TO_PORT リバースプロキシ接続先のポートを指定します
test_exmaple_com_PROXY_TO_URL リバースプロキシ接続先のURLを指定します
CLOUD_PROVIDER クラウドベンダー名を指定します。 Amazon または Google をサポートします
INTERNAL_IP Dockerコンテナが動作するホストのプライベートIPアドレスを指定する

解説

INTERNAL_IPCLOUD_PROVIDER について

  • リバースプロキシ先が nginx-certificate コンテナが動作する docker-compose にリンクされている場合は、 INTERNAL_IP=127.0.0.1 と指定することでリバースプロキシが実現できます
  • リバースプロキシ先が docker-compose 外で動作している場合、ホストのプライベートIPを指定する必要があります
  • AmazonまたはGoogleのクラウドを利用している場合 CLOUD_PROVIDER=Amazon のように指定することで、メタデータAPI経由でIPアドレスを解決することができます

リバースプロキシ先をURLで指定したい場合 (固定IPアドレスではなく、ドメインの場合)

  • リバースプロキシ先が固定IPの場合には、 <domain_name>_PROXY_TO_URL 設定値を利用します
  • nginxのupstreamコンテキストを利用する方法によって、有償オプションを利用することなく、動的な名前解決を実現しています。

証明書の取得と有効期間

  • 冒頭にも書きましたが、SSL証明書はLet's Encryptから自動取得を行います
  • 最初のアクセス時にSSL証明書の発行とRedisへの永続化を行っていますので、数秒〜十数秒の時間がかかります。一方で2回目以降のアクセス時にはRedisから証明書を取得するので応答までの時間は(通常のWebサイトであれば)気にならないレベルになるでしょう
$ time curl https://b.test.yumiyama.com -o /dev/null

real    0m7.602s
user    0m0.020s
sys     0m0.000s
$ time curl https://b.test.yumiyama.com -o /dev/null

real    0m0.068s
user    0m0.012s
sys     0m0.004s