Traefik Proxyに入門してみたメモ

# Traefik Proxyとは
https://traefik.io/traefik/

一言でいえば、リバースプロキシを実現するソフトウェアの一種です。
例えば、1台のマシンに複数のWebアプリケーションを立ち上げ、それらをアクセスされたサブドメインやURLによって振り分けたい時、エンドユーザ（ブラウザ）から見た窓口になってくれるのがリバースプロキシです。こいつはアクセスされた条件に応じて適切なWebアプリケーションにリクエストを振り、その結果を受け取り、エンドユーザに返すといった処理をします。

この用途ではWebサーバを立てるのによく使われるnginxが使われることも多いのですが、こちらの方が後発なだけあって色々使い勝手がよくなっているらしい。

Traefikシリーズ（？）のソフトは他にもありますが、本記事ではTraefik Proxyのことを単にTraefikと呼ぶことにします。

# 前提条件

本記事では、基本的にTraefikも含めたすべてのサービスをDockerを使って構築することにします。

- Windows 11 Home 23H2 の WSL2 環境
    - Ubuntu 22.04.4 LTS
    - Docker Desktop v4.33.1
    - Traefik Proxy v3.1.2

# 例1: 最初の一歩

まずは、Traefikが提供している whoami というサービス一つだけがあり、（ローカル環境で動作確認することを前提に）``http://localhost/`` というURLでアクセスさせたい場合を考えます。構成はこんな感じになるでしょう。（数字は待ち受けるポート番号を示します）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/0839e627-2c55-7f1f-e506-b4cfb65b4e26.png)

これを ``docker-compose.yml`` で書くと、以下のようになります。適宜コメントをつけます。

```docker-compose.yml
services:
  traefik:
    image: traefik:3.1.2
    command:
      # 個々のコンテナで明示的に公開設定を必要とする（不用意な公開防止）
      - --providers.docker.exposedByDefault=false
      # 80番ポートで待ち受ける web というエントリポイントを作成
      - --entryPoints.web.address=:80
    # Dockerの公開ポート設定
    ports:
      - 80:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock  # これはとりあえずおまじない

  whoami:
    image: traefik/whoami
    labels:
      # 明示的に公開する設定
      traefik.enable: true
      # web エントリポイントからのアクセスをルーティングする
      traefik.http.routers.whoami.entrypoints: web
      # localhost ドメインからのアクセスをルーティングする
      traefik.http.routers.whoami.rule: Host(`localhost`)
```

実はこれでTraefikはリバースプロキシとして動きます。
Webブラウザから ``http://localhost/`` にアクセスしてみると、以下のように出力されます。（コメントは筆者が追記したものです）

```
Hostname: ********
IP: 127.0.0.1
IP: ::1
IP: ********  # whoamiコンテナのIPアドレス
RemoteAddr: ********:**** # whoamiコンテナにアクセスしたサービス (Traefik) のIPアドレス・ポート番号
GET / HTTP/1.1 # 以下、リクエストヘッダが続く
Host: localhost
:
:
X-Forwarded-For: ******** # エンドユーザ（ネットワーク外から来ているので、ネットワークのゲートウェイ）のIPアドレス
X-Forwarded-Host: localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: ******** # Traefikのホスト名（コンテナ名）
X-Real-Ip: ******** # エンドユーザのIPアドレス
```

ここでのポイントとして、**Traefikコンテナの設定に各サービスの情報が一切登場しない**ことが挙げられます。すなわち、Traefikコンテナの設定変更や再起動をすることなく、サービス側の都合だけでサービスの追加・削除ができるということです。

nginxでリバースプロキシを実現する場合、**nginx側の設定に各サービスの情報を登録する必要があり、しかもその書いたサービスにアクセスできないとnginxが起動しない**という状態になります[^nginx_service_not_found]。Traefikの方が、柔軟に対応できそうです。

後は、目立ちませんが ``X-Forwarded-*`` のヘッダがデフォルトで付いてきます。nginxの場合、``proxy_set_header`` を使って手動で設定していたところです。

詳しいドキュメントの情報は全く示していませんが、サービスを追加したい時にどう書けばよいか、何となく類推できるのではないでしょうか。いくらドキュメントがあるといっても、直感的に分かる方が使いやすいことは言うまでもありません。

[^nginx_service_not_found]: 一応回避方法はあります。[nginx起動時に転送先が名前解決できなくてもエラーにしない方法 #nginx - Qiita](https://qiita.com/Yohko_Tanaka/items/0f9cb1c98eff3cc87962#%E8%A8%98%E8%BF%B0%E4%BE%8B)

# 例2: HTTPSで待ち受ける

続いて、最初の構成をHTTPSでのアクセスに対応させることにします。ここでは、TraefikでTLS接続を終端し、Traefikとwhoamiの間の通信は平文で行うことにします。つまり、以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/43a778e3-fab7-9c1d-5f41-5753b7372e2b.png)

``docker-compose.yml`` の設定を何行か追加・変更します。差分の箇所にコメントを付けています。

```docker-compose.yml
services:
  traefik:
    image: traefik:3.1.2
    command:
      - --providers.docker.exposedByDefault=false
      - --entryPoints.web.address=:80
      # 443番ポートで待ち受ける websecure というエントリポイントを作成
      - --entryPoints.websecure.address=:443
      # websecureではTLS接続を終端させる
      - --entryPoints.websecure.http.tls=true
    ports:
      - 80:80
      - 443:443 # 追加
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  whoami:
    image: traefik/whoami
    labels:
      traefik.enable: true
      # web および websecure エントリポイントからのアクセスをルーティングする
      traefik.http.routers.whoami.entrypoints: web,websecure
      traefik.http.routers.whoami.rule: Host(`localhost`)
```

これだけで、``http://localhost/`` および ``https://localhost/`` の両方のURLでwhoamiにアクセスすることができるようになります（証明書エラーはひとまず無視することとします）。とても簡単ですね。

# 例3: http:// でアクセスされたら https:// にリダイレクトさせる

近年は常時SSL/TLS化を設定することが普通になり、``http://`` でアクセスされたら ``https://`` にリダイレクトさせるという設定が必要となってきます。この場合は以下のようになります。

```docker-compose.yml
services:
  traefik:
    image: traefik:3.1.2
    command:
      - --providers.docker.exposedByDefault=false
      - --entryPoints.web.address=:80
      - --entryPoints.websecure.address=:443
      - --entryPoints.websecure.http.tls=true
      # http (web) でアクセスされたら https (websecure) にリダイレクト
      - --entrypoints.web.http.redirections.entryPoint.to=websecure
      - --entrypoints.web.http.redirections.entryPoint.scheme=https
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  whoami:
    image: traefik/whoami
    labels:
      traefik.enable: true
      # ここの待ち受け対象は websecure エントリポイントだけでよくなる
      traefik.http.routers.whoami.entrypoints: websecure
      traefik.http.routers.whoami.rule: Host(`localhost`)
```

# 例4: サービスを増やす

今までの例ではwhoamiだけが動いていたので、わざわざTraefikを使う必要はありません（SSL/TLS化の役割を担っているという見方はあるかもしれませんが）。
ここにもう一つ、別のサービスを加えることで、いよいよリバースプロキシとしての価値が出てきます。例として、8000番ポートでアクセスされたらnginx（Webサーバ）にリクエストを転送することを考えます。説明のために、HTTPSを用いない例1をベースとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/869616d6-29b3-69ee-ae81-311d3b2aa4d8.png)

```docker-compose.yml
services:
  traefik:
    image: traefik:3.1.2
    command:
      - --providers.docker.exposedByDefault=false
      - --entryPoints.web.address=:80
      # 8000番ポートで待ち受ける webapp というエントリポイントを作成
      - --entryPoints.webapp.address=:8000
    ports:
      - 80:80
      - 8000:8000 # 追加
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  whoami:
    image: traefik/whoami
    labels:
      traefik.enable: true
      traefik.http.routers.whoami.entrypoints: web # Port 80
      traefik.http.routers.whoami.rule: Host(`localhost`)

  # サービスを追加
  nginx:
    image: nginx:1.27.1-alpine3.20
    labels:
      traefik.enable: true
      traefik.http.routers.nginx.entrypoints: webapp # Port 8000
      traefik.http.routers.nginx.rule: Host(`localhost`)
```

これで、

- ``http://localhost/`` にアクセスするとwhoamiが実行される（リクエストヘッダが表示される）
- ``http://localhost:8000/`` にアクセスするとnginxのデモページが表示される

という状況になるはずです。（ブラウザキャッシュを消さないと、httpsへのリダイレクトが残ることがあります）
この時、**Traefik側の設定にnginxというコンテナの情報は一切出てきていません。**

# 例5: docker-compose.yml を分割する

実際には各サービスがこんなに単純な場合は少ないでしょう。例えばWebアプリを提供するNode.jsサーバは、DBサーバなどと連携して動きます。そしてサービス数が増えると、``docker-compose.yml`` のファイルをサービス単位で分け、サービスごとに個別に ``docker compose up/down`` したい場合が出てくるでしょう。

この場合、こんな感じの構成になると思われます。IPアドレス・サブネットは一例です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/eee52d7b-670e-d4dc-c6e2-a45b36a7b097.png)

``docker-compose.yml`` ごとにdefaultネットワークが一つできますが、異なるサービス同士はネットワークが分かれているので通信できません。そこで、相互通信用のネットワークを一つ別に作成し、つながる必要のあるコンテナをそのネットワークにも属させることを行います。ここではそのネットワークの名前を``shared``としています。

参考: [別々のdocker-compose環境同士でネットワーク間を連携する](https://zenn.dev/shimakaze_soft/articles/a91d9ec8b14a21)

初めに、コマンドで``shared``ネットワークを作成しておきます。

```bash:Terminal
docker network create shared
```

続いて、サービスごとに``docker-compose.yml``を作成します。例によって先ほどとの差分をコメントで示します。

```traefik/docker-compose.yml
services:
  traefik:
    image: traefik:3.1.2
    command:
      - --providers.docker.exposedByDefault=false
      - --entryPoints.web.address=:80
      - --entryPoints.webapp.address=:8000
    ports:
      - 80:80
      - 8000:8000
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

    # 自サービス内部用・他サービスとの通信用の両方のネットワークに所属させる
    networks:
      - default
      - shared

# リバースプロキシとサービスを接続するsharedネットワークを使用
networks:
  shared:
    external: true # docker-composeの外で定義される
```

```service1/docker-compose.yml
services:
  whoami:
    image: traefik/whoami
    labels:
      traefik.enable: true
      traefik.docker.network: shared # リバースプロキシとつながるネットワーク名を書く
      traefik.http.routers.whoami.entrypoints: web
      traefik.http.routers.whoami.rule: Host(`localhost`)

    # サービス用・リバースプロキシとの通信用の両方のネットワークに所属させる
    networks:
      - default
      - shared

# リバースプロキシとサービスを接続するsharedネットワークを使用
networks:
  shared:
    external: true
```

```service2/docker-compose.yml
services:
  nginx:
    image: nginx:1.27.1-alpine3.20
    labels:
      traefik.enable: true
      traefik.docker.network: shared # リバースプロキシとつながるネットワーク名を書く
      traefik.http.routers.nginx.entrypoints: webapp
      traefik.http.routers.nginx.rule: Host(`localhost`)

    # サービス用・リバースプロキシとの通信用の両方のネットワークに所属させる
    networks:
      - default
      - shared

# リバースプロキシとサービスを接続するsharedネットワークを使用
networks:
  shared:
    external: true
```

それぞれのディレクトリで  ``docker compose up -d`` を実行すれば、先ほどと同様に80番ポートと8000番ポートでそれぞれのサービスにアクセスできる状態になります。

ここまでやってしまえば、**Traefik側を一切操作することなく、whoamiやnginxを個別に ``docker compose up/down/restart/...`` することができる**ようになります。一つのサービスをメンテナンスするために、その他のサービスを停止する必要はありません。同様に、``docker-compose.yml``を追加することで、**基本的にTraefikを止めることなくサービスの新規追加が可能**となります。
（「基本的に」と書いたのは、ポートの開放を新たに設定する場合など、Traefikの再起動が必要になるケースもあるからです）

# 例6: サービスごとにドメイン名を分ける

例4, 5ではポート番号によってサービスを振り分けていましたが、実際問題としてはポートは80, 443固定として、ドメイン名（サブドメイン）によってサービスを振り分ける方が現実的です。

ここでは、whoamiを ``http://whoami.internal/`` 、nginxを ``http://nginx.internal/``  というURLでアクセスできるようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/02c54e24-2a5f-1576-c88b-cac9058383a0.png)

``C:\Windows\System32\drivers\etc\hosts`` ファイルに以下の2行を追記します（本番環境の場合はA/AAAAレコードを設定します）。
```
127.0.0.1 whoami.internal
127.0.0.1 nginx.internal
```

そして、各サービスの設定を変更します。といっても変更点は多くありません。

```traefik/docker-compose.yml
services:
  traefik:
    image: traefik:3.1.2
    command:
      - --providers.docker.exposedByDefault=false
      - --entryPoints.web.address=:80 # 8000番を削除
    ports:
      - 80:80 # 8000番を削除
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

    networks:
      - default
      - shared

networks:
  shared:
    external: true
```

```service1/docker-compose.yml
services:
  whoami:
    image: traefik/whoami
    labels:
      traefik.enable: true
      traefik.docker.network: shared
      traefik.http.routers.whoami.entrypoints: web # Port 80
      traefik.http.routers.whoami.rule: Host(`whoami.internal`) # ドメインを指定

    networks:
      - default
      - shared

networks:
  shared:
    external: true
```

```service2/docker-compose.yml
services:
  nginx:
    image: nginx:1.27.1-alpine3.20
    labels:
      traefik.enable: true
      traefik.docker.network: shared
      traefik.http.routers.nginx.entrypoints: web # Port 80
      traefik.http.routers.nginx.rule: Host(`nginx.internal`) # ドメインを指定

    networks:
      - default
      - shared

networks:
  shared:
    external: true
```

# 例7: 例6の構成をHTTPSに対応させる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204084/e4976997-5553-28c8-052e-78ccc4258505.png)

ここまでの流れでだいたいお気づきかもしれませんが、例1→例3の差分とほとんど同じです。
もう面倒なので差分だけ書いてしまいます。

```diff:traefik/docker-compose.yml
     command:
       - --providers.docker.exposedByDefault=false
       - --entryPoints.web.address=:80
+      - --entryPoints.websecure.address=:443
+      - --entryPoints.websecure.http.tls=true
+      - --entrypoints.web.http.redirections.entryPoint.to=websecure
+      - --entrypoints.web.http.redirections.entryPoint.scheme=https
     ports:
       - 80:80
+      - 443:443
```

```diff:service1/docker-compose.yml
     labels:
       traefik.enable: true
       traefik.docker.network: shared
-      traefik.http.routers.whoami.entrypoints: web
+      traefik.http.routers.whoami.entrypoints: websecure
       traefik.http.routers.whoami.rule: Host(`whoami.internal`)
```

```diff:service2/docker-compose.yml
     labels:
       traefik.enable: true
       traefik.docker.network: shared
-      traefik.http.routers.nginx.entrypoints: web
+      traefik.http.routers.nginx.entrypoints: websecure
       traefik.http.routers.nginx.rule: Host(`nginx.internal`)
```

証明書エラーは出ますが、それぞれのドメインでHTTPS接続ができて、http→httpsのリダイレクトも効きます。

# 例8: SSL/TLS証明書の設定

とはいえ、証明書エラーが出る状態で本番運用するわけにはいきません。何らかの方法で証明書を取得し、設定する必要があります。
本番環境であれば、もちろん正当な証明書を入手（Let's EncryptでもOK）する必要がありますが、ローカル環境で試す分にはオレオレ認証局を作成してオレオレ証明書を発行させるのが手軽でしょう。

[オレだよオレオレ認証局で証明書つくる #OpenSSL - Qiita](https://qiita.com/ll_kuma_ll/items/13c962a6a74874af39c6)
[openssl オレオレ認証局で証明書発行 #Ubuntu - Qiita](https://qiita.com/paseri2022/items/a250ccf415819996163b)

どこか適当なディレクトリで、以下のようにコマンドを実行します。（正当な証明書を持っている場合はスキップ）

```bash:Terminal
### 認証局の作成
mkdir demoCA
openssl genrsa -aes256 -out demoCA/cakey.pem 2048
  # パスワードは適当に…
openssl req -new -key demoCA/cakey.pem -out demoCA/cacert.csr
  #  Common Name には、oreore とか書いておく
openssl x509 -days 825 -in demoCA/cacert.csr -req -signkey demoCA/cakey.pem -out demoCA/cacert.pem
echo 00 > demoCA/serial

### 証明書の発行
mkdir demoCA/whoami.internal
mkdir demoCA/newcerts
echo "subjectAltName=DNS:whoami.internal" > demoCA/whoami.internal/san.txt
openssl genrsa -aes256 -out demoCA/whoami.internal/privkey.pem 2048
  # パスワードは適当に…
openssl req -new -key demoCA/whoami.internal/privkey.pem -out demoCA/whoami.internal/privkey.csr
  # Common Name にはアクセスさせるドメイン名を指定する (ここでは whoami.internal)
openssl ca -keyfile demoCA/cakey.pem -cert demoCA/cacert.pem -in demoCA/whoami.internal/privkey.csr -out demoCA/whoami.internal/privkey.crt.pem -days 825 -outdir demoCA/newcerts -extfile demoCA/whoami.internal/san.txt
  # y/nを聞かれたら y と答える
# パスワード外し
openssl rsa -in demoCA/whoami.internal/privkey.pem -out demoCA/whoami.internal/privkey-nopass.pem
```

メモ：
- OpenSSLの設定ファイルは、Ubuntu 22.04の環境だと /etc/ssl/openssl.cnf にある
- ``openssl ca`` というのは、``openssl.cnf`` の ``[ ca ]`` セクション（さらには ``[ CA_default ]`` も）を参照していることになる。設定中に ``./demoCA`` というパスが記述されているため、``demoCA`` というディレクトリを作成した

証明書を発行することができたら、この証明書を使用する設定を行います。TraefikでTLS接続を終端しているので、設定はTraefikのコンテナに対して行うことになります。

``dynamic-conf.yml`` ファイルを新規作成します。（正当な証明書を持っている場合は証明書のパスを適宜変更）

```dynamic-conf.yml
tls:
  certificates:
    - certFile: /demoCA/whoami.internal/privkey.crt.pem
      keyFile: /demoCA/whoami.internal/privkey-nopass.pem
      stores:
        - default
```

Traefikのコンテナの設定を変更します。差分は4行です。

```traefik/docker-compose.yml
services:
  traefik:
    image: traefik:3.1.2
    command:
      - --providers.docker.exposedByDefault=false
      - --entryPoints.web.address=:80
      - --entryPoints.websecure.address=:443
      - --entryPoints.websecure.http.tls=true
      - --entrypoints.web.http.redirections.entryPoint.to=websecure
      - --entrypoints.web.http.redirections.entryPoint.scheme=https
      - --providers.file.directory=/etc/traefik/dynamic_conf # 証明書の設定を追加
      - --providers.file.watch=true # 設定ファイルの変更を即時反映させる
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./dynamic-conf.yml:/etc/traefik/dynamic_conf/conf.yml:ro # 設定ファイルをマウント
      - /path/to/demoCA/whoami.internal:/demoCA/whoami.internal:ro # 証明書のディレクトリをマウント

    networks:
      - default
      - shared

networks:
  shared:
    external: true
```

そして、先ほど作成した ``demoCA/cacert.pem`` をWindows側のどこかのフォルダにコピーし、Firefox, Chromeなどの設定で、このファイルを認証局として追加します。これで、オレオレ証明書がブラウザに信頼される状態になりました。（正当な証明書を持っている場合はスキップ）

以上の手順により、``https://whoami.internal/`` にアクセスした場合に、証明書エラーが表示されない状態になります。

``nginx.internal`` については未対応なので、依然としてエラーが出ます。同じようにこちらも解決してみましょう。認証局は最初に作ったものを使いまわします。

```bash:Terminal
### 証明書の発行
mkdir demoCA/nginx.internal
echo "subjectAltName=DNS:nginx.internal" > demoCA/nginx.internal/san.txt
openssl genrsa -aes256 -out demoCA/nginx.internal/privkey.pem 2048
openssl req -new -key demoCA/nginx.internal/privkey.pem -out demoCA/nginx.internal/privkey.csr
  # Common Name にはアクセスさせるドメイン名を指定する (ここでは nginx.internal)
openssl ca -keyfile demoCA/cakey.pem -cert demoCA/cacert.pem -in demoCA/nginx.internal/privkey.csr -out demoCA/nginx.internal/privkey.crt.pem -days 825 -outdir demoCA/newcerts -extfile demoCA/nginx.internal/san.txt
openssl rsa -in demoCA/nginx.internal/privkey.pem -out demoCA/nginx.internal/privkey-nopass.pem
```

``dynamic-conf.yml`` を更新します。

```dynamic-conf.yml
tls:
  certificates:
    - certFile: /demoCA/whoami.internal/privkey.crt.pem
      keyFile: /demoCA/whoami.internal/privkey-nopass.pem
      stores:
        - default

    # 証明書を追加登録
    - certFile: /demoCA/nginx.internal/privkey.crt.pem
      keyFile: /demoCA/nginx.internal/privkey-nopass.pem
      stores:
        - default
```

``docker-compose.yml`` は1行増えます。

```diff:traefik/docker-compose.yml
     volumes:
       - /var/run/docker.sock:/var/run/docker.sock
       - ./dynamic-conf.yml:/etc/traefik/dynamic_conf/conf.yml:ro # 設定ファイルをマウント
       - /path/to/demoCA/whoami.internal:/demoCA/whoami.internal:ro # 証明書のディレクトリをマウント
+      - /path/to/demoCA/nginx.internal:/demoCA/nginx.internal:ro
```

これで ``docker compose up -d`` でコンテナを再作成すれば、``https://nginx.internal/`` にもエラーなしでアクセスできるようになるはずです。

# その他いろいろ

## アクセスログを取りたい

Traefikの ``docker-compose.yml`` において、以下の1行を追加
```diff:traefik/docker-compose.yml
     command:
       (略)
+      - --accessLog.filePath=/var/log/traefik.log
```
このパスはコンテナ内のパスなので、ローカル側で参照する必要がある場合は適宜 ``volumes`` の記述を追加してください。


## サービスの待ち受けポートが80以外の場合

Node.jsで構築されているサービスだと3000番ポートで待ち受けたりしますが、このように80番以外のポートで待ち受けるサービスに振り分けたい場合も、設定を1行追加すればOKです。

```yml
traefik.http.services.app.loadbalancer.server.port: 3000
```

## レスポンスをGZIPなどで圧縮したい

サービス側の ``docker-compose.yml`` の設定に追加すればOKです。例えば

```diff:service2/docker-compose.yml
     labels:
       (略)
+      traefik.http.routers.nginx.middlewares: test-compress
+      traefik.http.middlewares.test-compress.compress: true
+      traefik.http.middlewares.test-compress.compress.minresponsebodybytes: 100 # レスポンスのサイズが小さすぎると圧縮されないため
```

レスポンスが、リクエストの  ``Accept-Encoding`` ヘッダの値に応じて圧縮されます。nginxをDockerで使う場合、公式イメージではBrotliなどの新しめの形式に対応していませんが、Traefikだと公式イメージで使えます。筆者環境では zstd が優先的に使われるようでした。

現状、どの圧縮形式を使うか（優先順位）を指定する方法はないようです。[^default-encoding]
ただし、そのようなオプションを追加してほしいとのPull Requestが受理されており、近日中に正式リリースに反映されるのではないかと思います。

https://github.com/traefik/traefik/pull/10943

無事にリリースされた暁には、以下のような指定が可能となるはずです。
```
traefik.http.middlewares.test-compress.compress.encodings: br,gzip
```

[^default-encoding]: ``traefik.http.middlewares.test-compress.compress.defaultEncoding`` というオプションがありますが、これはリクエストヘッダに ``Accept-Encoding`` が指定されていない、もしくは ``*`` を含む場合のみ有効です。メジャーなブラウザは ``Accept-Encoding`` を送りますので、このオプションは効果がないということになります。

## HTTP/2やHTTP/3に対応したい

HTTPSの場合、特に何もしなくても HTTP/2 は有効化されるようです。
HTTP/3 を使いたい場合、**UDP** の443ポートを開け、Traefikの設定を追加します。

```diff:traefik/docker-compose.yml
     command:
       - --providers.docker.exposedByDefault=false
       - --entryPoints.web.address=:80
       - --entryPoints.websecure.address=:443
       - --entryPoints.websecure.http.tls=true
+      - --entryPoints.websecure.http3 # HTTP/3を有効化
       - --entrypoints.web.http.redirections.entryPoint.to=websecure
       - --entrypoints.web.http.redirections.entryPoint.scheme=https
       - --providers.file.directory=/etc/traefik/dynamic_conf
       - --providers.file.watch=true
     ports:
       - 80:80
       - 443:443
+      - 443:443/udp # HTTP/3用にポート開放
```

ただし、nginxの例はデモページが1ファイル ``/`` だけからなっており、最初のページは必ずHTTP/2で接続される（HTTP/3対応状況はレスポンスで通知される）ので、HTTP/3が効いているのかは分かりづらいです。ブラウザの開発者ツールでレスポンスの内容を確認して、

```
alt-svc: h3=":443"; ma=2592000
```

のようなヘッダが追加されていれば、設定は効いています。

## WebSocketを受け付けるには

リバースプロキシの背後に、クライアント（ブラウザ）とWebSocketで通信するサービスがある場合の話です。nginxだと追加で設定を書かなければ通信できませんが、Traefikの場合は何もしなくてもデフォルトでWebSocketが通ります。

## Let's Encryptで証明書の更新を自動化

ローカルのWSL2で確認するのは難しいので、別途試してみようと思います。とりあえず参考になりそうな記事へのリンクを。
[nginx-proxy(+acme-companion)からTraefikに移行してみる #Docker - Qiita](https://qiita.com/kthksgy/items/461f06c3f8a6323c5648)

# 最後に

この記事では個人的に使いそうなネットワーク構成を想定して、可能な限りシンプルな使い方を試してみたものです。より詳しくは公式ドキュメントへ。

公式ドキュメント: [Traefik Proxy Documentation - Traefik](https://doc.traefik.io/traefik/)