Traefik v2からv3への移行で注意すべき変更点
Traefik v3への移行時に発生する、static config内のswarmModeやpilotに関するエラーの解決策を解説します。ipWhiteListからipAllowListへの名称変更や、router ruleの構文変更、廃止されたproviderなど、移行時に動作が停止する具体的な注意点をまとめました。
Traefik v2 と v3 の違い
Traefik v2 から v3 への移行は、主に名前の変更作業です。有名な変更点として、middleware の ipWhiteList が ipAllowList に変わります。それ以外では、v3 では router rule の構文が厳格化されています(PathPrefix から regex 機能が削除され、いくつかの matcher が名称変更または削除されました)。また、一部の provider や option が完全に廃止されました。一方で、entrypoints、ACME 証明書の設定、Docker labels のワークフロー、および acme.json は引き続き利用可能です。さらに、v3 には v2 の rule 構文を維持する compatibility mode が搭載されています。これにより、バイナリを先にアップグレードし、リスクの高い一括作業を避けて、サービスごとにルールを書き換えることが可能です。
このガイドは、the Traefik reverse proxy guide で説明されている label ベースの Docker Compose 設定を前提としています。あちらのページは v3 専用ですが、このページはまだ traefik:v2 タグを使用している環境向けの内容です。
名称変更と削除
- HTTPおよびTCP middlewareの両方において、
ipWhiteListはipAllowListに変更されました。内部のオプションに変更はないため、sourcerangeの意味は変わりません。v3.5を含む現在のv3リリースでは、古い名称は非推奨のエイリアスとして引き続き受け入れられ、リストも維持されているため、この名称変更によって動作が停止することはありません。ただし、エイリアスは削除予定であり、予告なく非推奨リストから消えるため、名称変更は実施してください。 providers.docker.swarmMode=trueは削除されました。Swarmには、providers.swarm.endpointとして設定される独自のproviderが用意されています。pilotセクションは完全に削除されました。experimental.http3は削除されました。HTTP/3はentrypointで直接有効化します。- providersおよびforwardAuth middlewareから
tls.caOptionalが削除されました。 - InfluxDB v1 metrics provider、Rancher provider、およびMarathon providerが削除されました。
- TracingはOpenTelemetryに移行しました。JaegerやZipkinを含む専用のtracing backendは削除され、v3では代わりにOTLP (OpenTelemetry protocol) をエクスポートします。
- headers middleware内の非推奨な
ssl*オプション(sslRedirect、sslHost、その他)は削除されました。これらはentrypoint redirectionおよびredirectScheme middlewareに置き換えられました。
これらの削除は、見た目以上に重要です。Traefikは、静的設定(static configuration)に未知のオプションが含まれている場合、起動に失敗するためです。pilotやswarmModeの行が残っていると、コンテナは起動時にそのオプション名を明示したincompatible deprecated static option foundというメッセージと共に停止します。Traefikが全く知らないオプション(タイポやtls.caOptionalなど)がある場合は、代わりにfield not foundを表示して停止します。イメージのタグを変更する前に、静的設定をクリーンアップしてください。
Traefikが真に知らないmiddleware名(タイポ、またはエイリアス化されずに削除された名前)の場合、エラーの挙動が異なります。そのmiddlewareを参照しているrouterは、ルートとしてロードされる代わりにエラーでロードされ、dashboardにマークが表示され、APIはmiddleware "offce@docker" does not existを報告します。routerが起動しないため、そのhostnameへのリクエストは404となります。なお、現在のv3においてipwhitelistはこのカテゴリには含まれません。ipwhitelistは非推奨のエイリアスとして残っているため、名称を変更していなくても動作し続けます。
ルールの構文変更
ルールは、実際の書き換えが発生する箇所です。v3での変更点は以下の通りです。
- マッチャー内の値にはバッククォートが必要です。v2では二重引用符も使用可能でしたが、v3では使用できません。そのため、Host("app.example.com") は Host(
app.example.com) と記述する必要があります。 PathPrefixは、正規表現および{id}スタイルのプレースホルダーをサポートしなくなりました。v2 の PathPrefix(/api/{version:v[0-9]+}) のようなルールは、Go の正規表現構文で記述されたPathRegexpマッチャーに変更する必要があります。- マッチャーは単一の値のみを受け取るようになりました。v2 では Host(
app.example.com,www.example.com) が可能でしたが、v3 では Host(app.example.com) || Host(www.example.com) と記述します。例外はHeader、HeaderRegexp、Query、およびQueryRegexpで、これらは引き続き名前と値を受け取ります。 HeadersとHeadersRegexpは、それぞれHeaderとHeaderRegexpに名称変更されました。HostHeaderは削除されました。v3 で同じ対象にマッチするHostを使用してください。- 新しいマッチャーが2つ追加されました。ルール内でクライアントアドレスを照合するための
QueryRegexpとClientIPです。
良い点として、バッククォートを使用して記述された単純な Host(app.example.com) ルールは、そのまま v3 の構文として有効です。多くの小規模な Compose 設定はこの形式を使用しているため、ほとんどのラベルはルールの編集なしで移行できます。
開始前にラベルを監査する
grepによる検索1回で、移行の規模を測定できます。破壊的なラベルの変更には、grepで検出可能なパターンが存在するためです。
grep -rnE 'ipwhitelist|HostHeader|Headers\(|PathPrefix\(`[^`]*\{|Host\(`[^`]*`,' docker-compose*.ymlヒットした数だけ、編集が必要な行があります。ipwhitelist は ipallowlist になります。HostHeader は Host になります。Headers は Header になります。PathPrefix 内の {...} プレースホルダーは、PathRegexp マッチャーになります。Host() 内のカンマは、|| で結合された2つの Host() マッチャーになります。ヒットがゼロであれば、ラベルはすでに有効な v3 構文です。その場合、移行作業は静的設定と image tag の更新のみに限定されます。
変更されない点
EntrypointsおよびHTTPからHTTPSへのリダイレクト、両方のchallengeタイプに対応したACME resolvers、exposedByDefault、routerとserviceのlabels、loadbalancer.server.port、そしてdashboardは、v2と同様にv3でも動作します。v3はv2が作成したacme.jsonを読み込み続けるため、証明書もそのまま引き継がれます。ただし、作業前に必ずファイルのバックアップを取ってください。ファイルを失うロールバックを行うと、Let's Encryptのduplicate-certificateレート制限に直接抵触します。
cp ./letsencrypt/acme.json ./letsencrypt/acme.json.v2-backup移行手順
Step 1: 現在の実行環境を固定する。 traefik:latest または traefik:v2 タグを、使用中の正確なリリース(例: traefik:v2.11)に変更し、compose ディレクトリ全体を git に commit してください。これにより、後のステップをすべて checkout で元に戻せます。docker compose up -d <service> を使った単一サービスの再作成に慣れていない場合は、Docker Compose basics guide で本移行に必要な操作を確認してください。
Step 2: 静的設定をクリーンアップし、compatibility mode を有効にする。 v3 で廃止されたすべてのオプション(pilot, swarmMode, tls.caOptional, experimental.http3)を削除します。その後、v3 でルールをデフォルトで v2 構文として扱うよう設定します。traefik.yml では以下の通りです。
core:
defaultRuleSyntax: v2または、compose command: リストの flag として指定します: --core.defaultRuleSyntax=v2。compatibility mode はルール構文にのみ適用されます。削除されたオプションが復活したり、middleware の名前が自動的に変更されたりすることはありません。
Step 3: middleware の名称変更の準備。 compose ファイル内から古い名前(grep -rn ipwhitelist docker-compose*.yml)を検索します。すべての ipwhitelist ラベルを ipallowlist に書き換えます。ただし、まだ変更を適用しないでください。新しい名前は v2 には存在しないためです。これらの編集は、次のステップでの切り替え時に一括して適用します。(もし修正漏れがあっても、現在の v3 は古い名前を非推奨のエイリアスとして受け入れるため、動作は継続します。深夜に修正するのではなく、次のパスで修正してください。)
Step 4: image tag を切り替える。 Traefik の image を現在の v3 リリース(執筆時点では traefik:v3.5)に設定し、以下を実行します。
docker compose up -d
docker compose logs -f traefikcompatibility mode が有効なため、v2 のルールが引き続きマッチします。また、up -d によって middleware ラベルを書き換えたサービスの再作成も行われるため、ルーターは正常に起動します。正常なログには field not found 行も does not exist 行も含まれません。
このステップによるダウンタイムを考慮してください。v3 が認識できない middleware 名(タイポや削除されたオプション)を参照しているルーターは、新しい Traefik が起動してからアプリコンテナが再作成されるまで停止します。単一のホストでは、docker compose up -d がリストを処理する数秒間です。もしルートの停止を避けたい場合は、切り替え前にそのルーターの middlewares ラベルから名称変更した middleware を削除し、切り替え後に再追加してください。また、その間に IP allow list が使えなくなることを許容できるか、事前に判断してください。
Step 5: サービスごとにルールを移行する。 アプリケーションを一つずつ処理します。ルールを v3 構文に書き換え、そのサービスのみを docker compose up -d app で再作成し、次のステップへ進む前にテストしてください。まだ書き換えられないルールを持つサービスがある場合は、そのルーターに escape hatch ラベル traefik.http.routers.app.ruleSyntax=v2 を付与して、作業を続行してください。
Step 6: compatibility mode を無効にする。 すべてのルールが v3 構文になったら、defaultRuleSyntax と ruleSyntax ラベルを削除し、Traefik を再起動します。すべてのルーターが dashboard で green に表示されていることを確認してください。compatibility mode を使い続けないでください。Traefik は v3.4 でこれら両方のオプションを非推奨とし、次のメジャーバージョンで削除します。これらはあくまで移行のための手段です。
Before and after: one service's labels
以下は、複数の主要な変更が同時に適用されたアプリの例です。これには、multi-valueの Host、PathPrefix placeholder、および ipWhiteList middleware が含まれます。v2のブロックは以下の通りです。
app:
image: app:1.4
restart: unless-stopped
networks:
- proxy
labels:
- traefik.enable=true
- traefik.http.routers.app.rule=Host(`app.example.com`,`www.example.com`) && PathPrefix(`/api/{version:v[0-9]+}`)
- traefik.http.routers.app.entrypoints=websecure
- traefik.http.routers.app.tls.certresolver=le
- traefik.http.routers.app.middlewares=office
- traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24
- traefik.http.services.app.loadbalancer.server.port=8080同じサービスをv3に移行した例は以下の通りです。
app:
image: app:1.4
restart: unless-stopped
networks:
- proxy
labels:
- traefik.enable=true
- traefik.http.routers.app.rule=(Host(`app.example.com`) || Host(`www.example.com`)) && PathRegexp(`^/api/v[0-9]+`)
- traefik.http.routers.app.entrypoints=websecure
- traefik.http.routers.app.tls.certresolver=le
- traefik.http.routers.app.middlewares=office
- traefik.http.middlewares.office.ipallowlist.sourcerange=10.0.0.0/24
- traefik.http.services.app.loadbalancer.server.port=80802つのlabelが変更されました。ruleはmulti-valueの Host を || で結合された2つのmatcherに分割しました。また、placeholderを PathRegexp に置き換え、middleware labelの ipwhitelist を ipallowlist に変更しました。entrypoint、certificate resolver、router-to-middlewareの接続、およびservice portに変更はありません。
ダッシュボードで各サービスをテストする
設定を変更するたびに、ダッシュボードの HTTP routers ページを開いてください。すべての router が緑色である必要があります。エラーバッジが表示されている router は、具体的な問題を示しています。多くの場合、新しい名前で存在しない middleware や、v3 では解析できない rule が原因です。その後、ホスト名を一つずつ指定して、外部から接続を確認してください。
curl -sI https://app.example.com/api/v1/status200 またはアプリの通常の redirect が返されれば、routing と TLS の両方が正常に動作しています。Traefik から 404 が返される場合は、router が起動していません。ダッシュボードに戻り、エラー内容を確認してください。作業中は、別のターミナルで docker compose logs -f traefik を開いたままにしてください。コンテナが再起動するたびに、解析エラーがそこに記録されるためです。
Rollback honesty
すべてのサービスが v3 でルーティングされ、実際に動作確認ができるまで、v2 の compose file、静的設定、および acme.json のバックアップを保持してください。ロールバックの手順は、移行前の commit を checkout して docker compose up -d を実行することです。このとき、image tag だけではなく、ファイル全体を適用する必要があります。v3 専用の label は、v2 環境では正しく機能しないためです。これは、v2 で v3 専用の label が機能しなかった場合と同様の理由です。具体的には、v2 には ipallowlist が存在せず、PathRegexp matcher も解析できません。もし途中で acme.json が消失または破損した場合は、v2 を開始する前にバックアップから復元してください。そうしないと、ロールバック時に Let's Encrypt の rate limit を消費し、5 つの certificate を一度に再発行することになります。
FAQ
Traefik v3では、すべてのrouter ruleを書き換える必要がありますか?
いいえ。バックティックを使用した通常のHost(app.example.com) ruleは、両方のバージョンで有効です。これはほとんどのCompose構成に当てはまります。書き換えが必要なのは、v2独自の機能を使用している場合のみです。具体的には、PathやPathPrefix内でのregexまたはplaceholderの使用、1つのHost()内での複数のhostnameの指定、バックティックの代わりに引用符を使用している場合、および削除されたHeaders、HeadersRegexp、HostHeader matcherの使用が該当します。
Traefik v3でipWhiteListはどうなりましたか?
ipAllowListに名称変更されました。内部の設定内容は変更されていないため、v2のラベルであるtraefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24は、ipallowlistを含む同じ行になります。v3.5を含む現在のv3リリースでは、非推奨のエイリアスとして旧名称も引き続き受け入れられるため、名称を変更していなくても許可リストは静かに適用され続けます。ただし、これは一時的な措置と考えてください。エイリアスは削除予定です。Traefikが認識できないmiddleware名を使用すると、router errorと404が発生し、エラーが明示されます。ダッシュボードにエラーが表示され、そのhostnameへのリクエストは404を返します。
Traefik v3はv2のrule syntaxを読み取れますか?
はい。移行期間中は、static configurationでcore.defaultRuleSyntax: v2を設定することでv2 syntaxをデフォルトとして維持できます。デフォルトを戻した後は、個別の未対応ルールに対してrouterごとのruleSyntax=v2ラベルを使用してください。これらはどちらも一時的なものです。Traefikはv3.4でこれらを非推奨とし、次のメジャーバージョンで削除します。
Let's Encryptの証明書はアップグレード後も維持されますか?
はい。Traefik v3はv2が作成したacme.jsonファイルを読み込み続けるため、バイナリが変更されただけで証明書が再発行されることはありません。ただし、作業前にファイルを安全な場所にコピーしてください。ロールバックや、acme.jsonを失うボリュームの削除が発生すると、すべての証明書が一斉に再発行されます。Let's Encryptは、同一のhostnameセットに対して、1週間につき5つまでの重複証明書しか許可していません。
アップグレード後にTraefik v3が起動に失敗するのはなぜですか?
ほとんどの場合、static configurationにv3で削除されたオプションが残っていることが原因です。Traefikは認識できないオプションがある場合、起動を拒否します。よく知られた残存オプション(pilot、providers.docker.swarmMode、experimental.http3)の場合、ログにはincompatible deprecated static option foundと原因となる項目が表示されます。tls.caOptionalのようにv3が一度も認識したことのない項目の場合は、field not foundとノード名が表示されます。各項目を削除または置換してから、コンテナを再起動してください。