弁護士ドットコム株式会社 Creators’ blog

弁護士ドットコムがエンジニア・デザイナーのサービス開発事例やデザイン活動を発信する公式ブログです。

クラウドネイティブ時代のプロキシTraefikのDocker入門

こんにちは。税理士ドットコム事業部の @komtaki です。

先日、税理士ドットコムの local 環境に「クラウドネイティブ時代のリバースプロキシ」Traefikを導入しました。プロキシサーバーの候補として最初に思いついたのは nginx でしたが、最終的には、設定ファイル不要で compose.yml だけで完結する Traefik に決めました。

そこで本記事では、Docker を前提としたコンテナのラベルでの設定方法など、導入の過程で調べた Traefik を使うために必要な情報をまとめています。

なお Traefik にはロードバランサーの機能もあるのですが、ここではプロキシの機能に焦点を当てて説明します。

Traefik とは

Traefik は、クラウドネイティブなリバースプロキシおよびロードバランサーとして設計されたオープンソースツールです。マイクロサービスやコンテナ化されたアプリケーションの運用に特化しており、動的な環境でのトラフィック管理を容易にします。

さらに Docker、Kubernetes、AWS ECS など、さまざまなプロバイダーをサポートしています。

traefik.io

主な特徴

  • リバースプロキシ: 外部からのリクエストを受け、内部のサービスに転送できます。これにより、複数のサービスを一元的に管理できます。
  • ロードバランシング: 複数のバックエンドサービスにトラフィックを均等に分散させ、システム全体のパフォーマンスや可用性を向上させます。
  • 自動サービス検出: Kubernetes や Docker などと統合して、サービスの追加や削除を自動的に検出し、ルーティング設定を動的に更新します。手動設定を最小限に抑え、変更に柔軟に対応できるのが大きな利点です。
  • 自動SSL/TLS管理: Let's Encrypt などを利用して SSL 証明書を自動で取得・更新し、HTTPS 接続を簡単に設定できます。
  • Observability(可観測性): Prometheus や DataDog などの監視ツールと連携し、トラフィックのログやメトリクスを収集して、システムのパフォーマンスやエラーの監視ができます。

Docker での基本的な設定

Traefik の本体の設定

公式 docker イメージが公開されており、yaml, toml, cli の 3 つの方法で設定できます。ファイルの場合、/etc/traefik/traefik.yml にマウントします。

docker run -d -p 8080:8080 -p 80:80 \
  -v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v3.1

本記事では dokcer compose を前提として、cli の設定でサンプルを記述しています。

  proxy:
    image: traefik:v3.1
    ports:
      - 80:80
    command:
      - --providers.docker
      - --providers.docker.exposedByDefault=false
      - --entrypoints.web.address=:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

デフォルトでは Traefik を通じてすべてのコンテナが公開されます。そのため、exposedByDefaultを false にして、個別でサービスにラベルをつけて有効にすることをお勧めします。

main:
  labels:
    traefik.enabled: true

Traefik Installation Documentation - Traefik

ラベルでサービスごとの設定

Traefik では Docker エンジンのラベルを監視しています。ルーティングに限らずラベルで設定でき、nginx のような設定ファイルが不要です。そのため Traefik 自体の再起動は不要で、サービスディスカバリーでサービス側の再起動だけで済みます。

api:
  labels:
    traefik.http.routers.main.rule: PathPrefix(`/api`)

Traefik Docker Documentation - Traefik

ポート検知

この時ポート番号は、Docker API を使って 3 パターンで検知されます。

  • 1つのポートが公開 (Docker で expose) されている場合、そのポートを使用します。
  • 複数のポートが公開されている場合、もっとも小さい番号のポートを使用します。 例えば、80 と 8080 が公開されている場合、80 を使用します。
  • それ以外の場合で、traefik.http.services.<サービス名>.loadbalancer.server.port というラベルで指定されているポートがあれば、そのポートを使用します。
EXPOSE 80

Traefik Docker Documentation - Traefik

ルーティングの設定

代表的なルールの設定

以下がよく使うルールですが、かなり豊富なパターンで記述できます。

名前 記述例 マッチする例
ホストの完全一致 Host(`www.zeiri4.local`) www.zeiri4.local
ホストの正規表現一致 HostPrefex(`^.*\.zeiri4\.local`) www.zeiri4.local
パスの完全一致 Path(`/products`) /products
パスの先頭一致 PathPrefex(`/products`) /products/2/
パスの正規表現一致 PathRegex(`^/products/[0-9]+/$`) /products/2/
メソッドの一致 Method(`OPTIONS`) OPTIONS
ヘッダーの完全一致 Header(`Content-Type`, `application/yaml`) application/yaml
ヘッダーの正規表現一致 HeaderRegexp(`Content-Type`, `^application/(json|yaml)$`) application/yaml, application/json

Traefik Routers Documentation - Traefik

優先度の決まり方

デフォルトで優先度はルールの長さが長い順になります。そのため多くのケースで明示的に優先度を指定する必要はありません。

例えば、サービスが 3 つあり下記のように compose.yaml でルールが設定されているとします。

main:
  labels:
    traefik.http.routers.main.rule: `PathRegex(.*)`

backyad:
  labels:
    traefik.http.routers.backyard.rule: `PathPrefix(/backyard/)`

api:
  labels:
    traefik.http.routers.api.rule: `PathPrefix(/api/)`

この場合、優先度は下記のように計算され、backyard, api, main の順でルールが適応されてます。

サービス名 ルール 優先度(文字数)
main PathRegex(`.*`) 15
api PathPrefix(`/api/`) 19
backyard PathPrefix(`/backyard/`) 24

Traefik Routers Documentation - Traefik

オブザーバビリティの設定

トラフィックの状態を監視する機能も充実しています。もちろんデバッグなどにも非常に有効です。

ダッシュボード

Traefik ではダッシュボードが提供されており、各サービスの状態やルーティングの優先度を確認できます。有効化すると、http://localhost:8080/dashboard/で見られます。

またこの時、Traefik の内部APIを外部公開する必要があるため、api の insecure モードも同時に有効化する必要があります。これにより、http://localhost:8080/api/entrypointsなどでデータが取れるようになります。

proxy:
  command:
    - --api.insecure=true
    - --api.dashboard=true
  ports:
    - 8080:8080

ダッシュボードTOP
ダッシュボード HTTP Router

Traefik Dashboard Documentation - Traefik

アクセスログ

アクセスログの機能もあり、設定で有効化するとデフォルトで標準出力に出力されます。ファイルパスの指定も可能です。

proxy:
  command:
    - --accesslog=true

デフォルトでは Apache と同じ Common Log Format のログが出力されますが、format オプションで JSON などに整形できます。

172.18.0.0 - - [11/Sep/2024:07:00:44 +0000] "GET /api/ HTTP/1.1" 200 71356 "-" "-" 1 "api@docker" "http://172.18.0.4:80" 2202ms

Traefik Access Logs Documentation - Traefik

トラブルシューティング

「404 Not Found」が表示される

リクエストに合致するルーターがない場合、404 が表示されます。ルーティングの設定があっているか確認しましょう。

Traefik Getting Started FAQ - Traefik

「502 Gateway Error」が表示される

サービスは検知できていますが、ポートマッピングがおかしい可能性があります。ポートが自動で検知できない場合、ラベルでポート番号を指定しましょう。

Traefik Getting Started FAQ - Traefik

まとめ

ポートやサービスの自動検知、ルーティングの優先度の計算など、痒いところに手が届いています。それゆえ設定が簡単すぎて「本当にこれで大丈夫なのか」「どうして動いているのか」と調べることのほうが多かったです。

本記事では触れませんでしたが、TLS や認証の設定も簡単にできそうです。

コンテナ環境でのリバースプロキシの候補の 1 つとして Traefik はいかがでしょうか。