こんにちは。税理士ドットコム事業部の @komtaki です。
先日、税理士ドットコムの local 環境に「クラウドネイティブ時代のリバースプロキシ」Traefikを導入しました。プロキシサーバーの候補として最初に思いついたのは nginx でしたが、最終的には、設定ファイル不要で compose.yml だけで完結する Traefik に決めました。
そこで本記事では、Docker を前提としたコンテナのラベルでの設定方法など、導入の過程で調べた Traefik を使うために必要な情報をまとめています。
なお Traefik にはロードバランサーの機能もあるのですが、ここではプロキシの機能に焦点を当てて説明します。
Traefik とは
Traefik は、クラウドネイティブなリバースプロキシおよびロードバランサーとして設計されたオープンソースツールです。マイクロサービスやコンテナ化されたアプリケーションの運用に特化しており、動的な環境でのトラフィック管理を容易にします。
さらに Docker、Kubernetes、AWS ECS など、さまざまなプロバイダーをサポートしています。
主な特徴
- リバースプロキシ: 外部からのリクエストを受け、内部のサービスに転送できます。これにより、複数のサービスを一元的に管理できます。
- ロードバランシング: 複数のバックエンドサービスにトラフィックを均等に分散させ、システム全体のパフォーマンスや可用性を向上させます。
- 自動サービス検出: 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
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 はいかがでしょうか。