Docker: HTTPSルーティング

DockerコンテナでのHTTPルーティングとTLS暗号化(HTTPS)の管理方法

👋 Stackheroのドキュメントへようこそ!

Stackheroは、DockerクラウドCaaS (Containers as a Service) の即時利用可能なソリューションを提供し、多くの利点があります。例えば:

  • docker-compose up だけでコンテナを簡単に本番環境にデプロイ
  • HTTPSで保護されたカスタマイズ可能なドメイン名(例: https://api.your-company.com, https://www.your-company.com, https://backoffice.your-company.com)。
  • プライベートで専用のVMによる最適なパフォーマンスと強力なセキュリティ
  • ワンクリックでの簡単なアップデート

時間を節約し、生活を簡素化:StackheroのDocker CaaSクラウドホスティング ソリューションを試して、コンテナを本番環境にデプロイするのに5分しかかかりません!

Stackhero for Dockerインスタンスには、HTTPトラフィックを管理し、TLS証明書を使用して自動的に暗号化する専用の事前設定されたTraefikサーバーが含まれています。この簡素化されたセットアップにより、ルーティングが簡単かつ効率的になります。例えば:

  • https://www.my-company.com(wwwプレフィックスの有無にかかわらず)からfrontendコンテナにトラフィックを送信します。
  • https://www.my-company.com/documentationsdocumentationsコンテナにルートします。
  • https://api.my-project.ioapiコンテナに直接送信します。

無制限のドメインを自動TLS証明書の作成と更新で管理できます。さらに、これをわずか3行で設定できます!

以下のすべての設定例では、<XXXXXX>.stackhero-network.comStackhero for Dockerインスタンスのドメイン名に置き換える必要があります。

以下はdocker-compose.ymlファイルの基本例です:

services:
  test:
    image: nginx
    labels:
      - "traefik.enable=true" # このコンテナへのトラフィックをルートするためにTraefikを有効にする
      - "traefik.http.routers.test.rule=Host(`<XXXXXX>.stackhero-network.com`)" # ホストを定義する
      - "traefik.http.routers.test.tls.certresolver=letsencrypt" # 'letsencrypt'をTLS証明書のリゾルバーとして使用する

この例では、testという名前のコンテナがNginxイメージを使用して実行されます。キー設定はラベルセクションに提供されています。これらの行をdocker-compose.ymlファイルにコピーし、<XXXXXX>.stackhero-network.comをサービスドメインに置き換えるだけです。

コンテナをデプロイするには、以下を使用します:

docker context use <XXXXXX>.stackhero-network.com
docker-compose up

コンテナが起動したら、https://<XXXXXX>.stackhero-network.com/を訪問して「Welcome to nginx!」ページを確認してください。

NginxウェルカムページNginxウェルカムページ

Nginxのウェルカムページが表示されない場合は、Traefikダッシュボードでエラーを確認してください!

この設定により、<XXXXXX>.stackhero-network.comに送信されたHTTPリクエストはtestコンテナにルートされ、TraefikはHTTPS用のTLS証明書を自動的に作成および管理します。

前の例では、デフォルトの<XXXXXX>.stackhero-network.comドメインを使用しました。実際には、www.my-company.comapi.my-project.ioなどの独自の会社やプロジェクトのドメインを使用することが多いでしょう。以下のセクションでは、カスタムドメインの設定方法を説明します。

この例では、api.my-project.ioドメインを設定します。my-project.ioを所有するドメインに置き換え、apiを希望するサブドメインに置き換えてください。

まず、api.my-project.io<XXXXXX>.stackhero-network.comドメインを指すようにドメインのDNS設定を更新します。

  1. ドメインプロバイダーにログインし、DNS設定にアクセスします。
  2. api(または希望する他のサブドメイン)という名前の新しいエントリを作成し、そのタイプをCNAMEに設定し、宛先を<XXXXXX>.stackhero-network.comに設定します。

Cloudflare DNSインターフェースでのDNS設定例Cloudflare DNSインターフェースでのDNS設定例

DNSが設定されたら、以下を実行して確認できます:

host api.my-project.io

次のような応答が表示されるはずです:

api.my-project.io is an alias for <XXXXXX>.stackhero-network.com

DNSの伝播はプロバイダーによって最大24時間かかる場合があります。 hostコマンドが期待される応答を返さない場合は、しばらく待ってから再試行してください。

次に、以下の設定でdocker-compose.ymlファイルを更新します:

services:
  api:
    image: traefik/whoami
    hostname: api
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.my-project.io`)" # ここにドメインを追加
      - "traefik.http.services.api.loadbalancer.server.port=<PORT>" # "<PORT>"をAPIがリスニングしているポートに置き換える
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"

TraefikラベルHostapi.my-project.ioを実際のドメインに置き換えることを忘れないでください。

コンテナをデプロイするには:

docker-compose up -d

次に、https://api.my-project.ioを訪問します。コンテナのホスト名apiが表示されるテキストページが表示されるはずです。

新しいドメインのためにTraefikがHTTPトラフィックをTLS暗号化で処理している証拠新しいドメインのためにTraefikがHTTPトラフィックをTLS暗号化で処理している証拠

コンテナの初回作成時には、TLS証明書の生成に数秒かかる場合があります。 TLSエラーが発生した場合は、数秒待ってページを更新し、証明書が生成される時間を確保してください。

おめでとうございます、最初のカスタムドメインを設定しました!

my-company.comのようなウェブサイトURLを定義する際には、「www」サブドメインも設定することをお勧めします。これにより、www.my-company.comを介して接続するユーザーがメインサイトにリダイレクトされ、重複コンテンツの問題を回避できます。

以下の例では、my-company.comwww.my-company.comの両方が処理されます。www.my-company.comにアクセスするユーザーはmy-company.comにリダイレクトされます:

services:
  frontend:
    image: traefik/whoami
    hostname: frontend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`my-company.com`) || Host(`www.my-company.com`)" # 両方のドメインをここに追加
      - "traefik.http.services.frontend.loadbalancer.server.port=<PORT>" # "<PORT>"をフロントエンドがリスニングしているポートに置き換える
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"

      # 'www.my-company.com'を'my-company.com'にリダイレクト:
      - 'traefik.http.routers.frontend.middlewares=redirect-www'
      - "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)"
      - "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}"
      - "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"

ドキュメントサイト専用のコンテナがあるとします。https://my-company.com/docsをこのコンテナにルートし、他のリクエスト(例えばhttps://my-company.com/)をフロントエンドコンテナに送信したい場合があります。以下の例では、これがどのように実現されるかを示しています:

services:
  documentations:
    image: traefik/whoami
    hostname: documentations
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.documentations.rule=Host(`my-company.com`) && PathPrefix(`/docs`)" # ここでパスプレフィックスを定義
      - "traefik.http.services.documentations.loadbalancer.server.port=<PORT>" # "<PORT>"をドキュメントコンテナがリスニングしているポートに置き換える
      - "traefik.http.routers.documentations.tls.certresolver=letsencrypt"

  frontend:
    image: traefik/whoami
    hostname: frontend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`my-company.com`) || Host(`www.my-company.com`)"
      - "traefik.http.services.frontend.loadbalancer.server.port=<PORT>" # "<PORT>"をフロントエンドがリスニングしているポートに置き換える
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"

      # 'www.my-company.com'を'my-company.com'にリダイレクト:
      - 'traefik.http.routers.frontend.middlewares=redirect-www'
      - "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)"
      - "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}"
      - "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"

これで、https://my-company.com/docs(またはhttps://my-company.com/docs/somethingのようなサブパス)を訪問すると、documentationsコンテナのコンテンツが表示されます。他のパス、例えばhttps://my-company.com/helpfrontendコンテナによって提供されます。

デフォルトでは、Traefikはコンテナの最初に公開されたポートに接続します。場合によっては、特定のポートを指定する必要があるかもしれません。以下の例では、カスタムポートを定義する方法を示しています:

services:
  frontend:
    image: traefik/whoami
    hostname: frontend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`my-company.com`)"
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"

      # 'https://my-company.com'から'frontend'コンテナへのトラフィックをポート80でルート
      - "traefik.http.services.frontend.loadbalancer.server.port=80"

docker-compose.ymlファイルでコンテナを定義する際、より良い一貫性と管理のしやすさのために重要なフィールドがいくつかあります。以下の推奨設定を使用することを検討してください:

services:
  <CONTAINER_NAME>:
    image: traefik/whoami
    hostname: <CONTAINER_NAME>
    container_name: <CONTAINER_NAME>
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.<CONTAINER_NAME>.rule=Host(`my-company.com`)"
      - "traefik.http.routers.<CONTAINER_NAME>.tls.certresolver=letsencrypt"

<CONTAINER_NAME>を希望するコンテナ名、例えばfrontendに置き換えてください。

サブドメインを作成する際、Let's EncryptはRFC 952および1123に従い、[a-zA-Z0-9-]のセット内の文字のみを許可します。

アンダースコア('_')はDNSレコード名では許可されていますが、ホスト名では許可されていません。その結果、Let's Encryptは「my_subdomain.example.com」のようなサブドメインを拒否し、「ドメイン名に無効な文字が含まれています」というエラーを表示します。

この問題を解決するには、サブドメインからアンダースコアを削除するだけです。