Traefik は ACME を介して証明書を自動発行できることで有名です。しかし、それではなく自前の証明書を持ち込む必要がある場合もあります。たとえば GetHTTPS で発行したもの、社内・内部 CA のもの、あるいは別の場所で管理しているワイルドカード証明書などです。このガイドでは、Traefik v3 でその方法を正確に説明します。
最初に理解しておくべき重要な点は、証明書ファイルを Docker ラベルで割り当てることはできないということです。Traefik のラベルはルーティングを制御し、TLS を有効化しますが、証明書そのものは動的設定として file プロバイダーから渡さなければなりません。これは初回にほぼ全員がつまずくポイントです。正しいやり方で進めていきましょう。
まだ証明書をお持ちでない場合は、5分で無料で取得できます。
いつこの方法を使うか(Traefik 自動 ACME との比較)
| 自動 ACME(Let’s Encrypt)を使う | 自前の証明書を持ち込む(このガイド) |
|---|---|
| 公開ウェブサイトでインターネットから到達可能 | 内部・イントラネット向けサービス(公開 DNS なし) |
| 標準的な DV 証明書で十分 | 特定の CA、ワイルドカード、または OV/EV 証明書が必要 |
| Traefik が HTTP/DNS チャレンジを完了できる | エアギャップ環境やファイアウォール内のホスト |
| 証明書管理をいっさい行いたくない | GetHTTPS などで取得した証明書をすでに持っている |
自動 ACME が条件に合うなら、Traefik の certificatesResolvers の方がシンプルです。このガイドは、「すでに fullchain.pem + privkey.pem を持っていて、それを Traefik に配信させたい」というケース向けです。
前提条件
- Traefik v3 を Docker コンテナとして実行していること(以下の設定では Docker を使いますが、動的設定の部分はどのような構成にも適用できます)
- 証明書ファイル — 次の2つ:
fullchain.pem— 証明書 + 中間チェーンprivkey.pem— 秘密鍵
- ホストを指すドメイン(または内部利用向けのローカル hosts ファイルのエントリ)
Traefik にはどのファイルが必要か? Traefik は
certFileにフルチェーン、keyFileに鍵を求めます。リーフのみのcert.pemを使うと、クライアント側で「チェーンが不完全」というエラーが出ます。Traefik は file プロバイダーの証明書に対して中間証明書を自動付加しません。fullchain.pemを使ってください。証明書フォーマットの解説 →
Traefik の設定はどう分かれているか
Traefik には2種類の設定があり、証明書は2つ目に存在します:
- 静的設定(Static configuration) — 起動時に設定されます(entrypoint、プロバイダー)。変更には再起動が必要です。これは
traefik.ymlまたはコンテナのコマンドフラグに記述します。 - 動的設定(Dynamic configuration) — 再起動なしでライブにリロードされます(router、サービス、TLS 証明書)。これが file プロバイダーが読み込む対象です。
証明書は動的設定です。だからこそラベルには載せられません。ラベルは Docker プロバイダーから読み込まれますが、tls.certificates は file プロバイダーの概念だからです。
ステップ1: 証明書ファイルを配置する
コンテナにマウントするディレクトリにファイルを置きます:
mkdir -p ./traefik/certs
cp fullchain.pem ./traefik/certs/
cp privkey.pem ./traefik/certs/
# 秘密鍵をロックダウンする
chmod 600 ./traefik/certs/privkey.pem
chmod 644 ./traefik/certs/fullchain.pem
ステップ2: 動的設定を書く
./traefik/dynamic/certs.yml を作成します。ここで証明書を宣言します:
# ./traefik/dynamic/certs.yml (動的設定 — file プロバイダー)
tls:
certificates:
- certFile: /certs/fullchain.pem
keyFile: /certs/privkey.pem
# オプション: より具体的な証明書(ワイルドカードや内部 CA など)に
# マッチしないあらゆるホストに対して、この証明書をデフォルトにする。
stores:
default:
defaultCertificate:
certFile: /certs/fullchain.pem
keyFile: /certs/privkey.pem
パス(/certs/...)はコンテナ内のパスです。次のステップでマウントします。Traefik は SNI を使ってリクエストごとに適切な証明書を選択し、証明書の SAN を要求されたホスト名と照合します。defaultCertificate は他に何もマッチしないときのフォールバックです。
ステップ3: Traefik を設定する(静的設定 + マウント)
完全な docker-compose.yml を以下に示します。entrypoint と file プロバイダーは静的設定(コマンドフラグとして渡す)で、証明書は先ほど書いた動的ファイルから読み込まれます。
services:
traefik:
image: traefik:v3.3
container_name: traefik
restart: unless-stopped
command:
# ─── Entrypoints ───────────────────────────────
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# すべての HTTP を entrypoint レベルで HTTPS にリダイレクトする
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
# ─── Providers ─────────────────────────────────
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
# file プロバイダーが動的設定ディレクトリを監視する
- "--providers.file.directory=/dynamic"
- "--providers.file.watch=true"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./traefik/certs:/certs:ro"
- "./traefik/dynamic:/dynamic:ro"
# ─── バックエンドサービスの例 ──────────────────────
whoami:
image: traefik/whoami
container_name: whoami
labels:
- "traefik.enable=true"
# Router: ホストにマッチさせ、HTTPS entrypoint で配信する
- "traefik.http.routers.whoami.rule=Host(`example.com`)"
- "traefik.http.routers.whoami.entrypoints=websecure"
# この router で TLS を有効にする — 証明書はラベルではなく
# 動的設定から来る。
- "traefik.http.routers.whoami.tls=true"
最も重要な行は traefik.http.routers.whoami.tls=true です。 これは Traefik に「この router を TLS で配信する」よう指示します。すると Traefik は SNI によって file プロバイダーのストアから一致する証明書を選びます。tls.certfile のようなラベルは存在しません — それは router には存在しないのです。
ステップ4: 起動して検証する
docker compose up -d
docker compose logs -f traefik
file プロバイダーが証明書を読み込むのを確認してください。TLS エラーは出ないはずです。次に検証します:
ブラウザでの確認
https://example.com にアクセスします。鍵アイコンをクリックします:
- 発行者 — あなたの CA(GetHTTPS なら Let’s Encrypt、または社内 CA)
- 有効期間 — 開始日と終了日
- ドメイン — URL と一致している
コマンドラインでの確認
# Traefik が自己署名のデフォルトではなく、あなたの証明書を配信していることを確認する
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
CN=TRAEFIK DEFAULT CERT と表示される場合、Traefik は組み込みのプレースホルダーにフォールバックしています。つまり証明書が読み込まれていません。下記のトラブルシューティングセクションを参照してください。
ステップ5(オプション): TLS を強化する
プロトコルバージョンや暗号スイートを制御するには、動的設定に TLS オプションブロックを追加し、router から参照します。certs.yml に次を追加します:
tls:
options:
modern:
minVersion: VersionTLS12
sniStrict: true
次に router のラベルで:
- "traefik.http.routers.whoami.tls.options=modern@file"
@file というサフィックスは、このオプションセットが file プロバイダー由来であることを Traefik に伝えます。これにより TLS 1.2 と 1.3 に限定され、一致する SNI がない接続を拒否します。
HSTS: HTTPS がどこでも問題なく動作すると確信できたら、Traefik の
headersミドルウェアを介してStrict-Transport-Securityヘッダーを追加してください。HSTS ガイド →
更新の方法
Traefik は、あなたが自分で用意した証明書を自動更新しません — これが自前で持ち込むことのトレードオフです。証明書の有効期限が近づいたら(Let’s Encrypt なら90日のうち60日目):
- GetHTTPS(またはお使いの更新ツール)から新しい証明書を取得します。
- ファイルをその場で上書きします:
cp new-fullchain.pem ./traefik/certs/fullchain.pem cp new-privkey.pem ./traefik/certs/privkey.pem - それ以外は何もしません。
--providers.file.watch=trueが設定されているため、Traefik はファイルの変更を検知して証明書をホットリロードします — 再起動も、ダウンタイムもありません。これはカスタム証明書における Traefik の最も優れた特性の一つです。
トラブルシューティング
Traefik が自分の証明書ではなく「TRAEFIK DEFAULT CERT」を配信する
原因: Traefik があなたの証明書を読み込めず、自己署名のプレースホルダーにフォールバックしました。ほぼ必ずパスまたはマウントの問題です。
対処:
# 1. ファイルが想定したパスでコンテナ内に存在することを確認する
docker compose exec traefik ls -l /certs
# 2. 動的ファイルがマウントされ、読み取り可能であることを確認する
docker compose exec traefik cat /dynamic/certs.yml
# 3. ログで本当の理由を確認する
docker compose logs traefik | grep -i "certificate\|tls\|error"
certs.yml の certFile/keyFile のパスは、ホスト側のパスではなくコンテナのパス(/certs/...)と一致していなければなりません。
「unable to find certificate for domain」/ 間違った証明書が配信される
原因: どの証明書の SAN も要求されたホスト名にマッチせず、defaultCertificate も設定されていません。
対処: ホスト名を証明書に追加するか、stores.default ブロック(ステップ2)に defaultCertificate を設定して、Traefik にフォールバックを持たせてください。
router が 404 を返し、証明書がそもそもチェックされない
原因: router のルールがマッチしないか、サービスが公開されていません。ルーティングがマッチするまで TLS は関係ありません。
対処:
# router が存在し、有効になっていることを確認する
docker compose exec traefik wget -qO- http://localhost:8080/api/http/routers 2>/dev/null | grep whoami
バックエンドのコンテナに traefik.enable=true が付いており、Host() ルールがテスト対象のドメインにマッチしていることを確認してください。
certs.yml への変更が反映されない
原因: file プロバイダーが監視していないか、静的設定(再起動が必要)を編集しました。
対処: --providers.file.watch=true が静的設定にあることを確認してください。覚えておいてください: entrypoint/プロバイダーは静的(再起動が必要)で、router と tls.certificates は動的(ホットリロードされる)です。
クライアントから「x509: certificate signed by unknown authority」が出る
原因: チェーンが不完全です — certFile に fullchain.pem ではなくリーフのみの cert.pem を使いました。
対処: certFile をフルチェーンに向けてください。別々のファイルしか持っていない場合は、それらを連結します(リーフが先、続いて中間証明書):
cat cert.pem intermediate.pem > fullchain.pem
よくある質問
Docker ラベルで証明書ファイルを指定できますか?
いいえ。 これは最大の誤解です。ラベルは traefik.http.routers.<name>.tls=true を設定して TLS を有効化しますが、証明書ファイルは file プロバイダーを介して動的設定(tls.certificates)で宣言しなければなりません。.pem ファイルを指す router ラベルは存在しません。
証明書があれば router に tls=true は必要ですか?
はい。証明書を tls.certificates で宣言すると利用可能になりますが、各 router が実際に HTTPS で配信するには、依然として tls=true(または TLS が有効な entrypoint でのリッスン)が必要です。証明書を定義しただけでは router は TLS に切り替わりません。
自動 ACME とカスタム証明書を併用できますか?
はい。Traefik は一部の router に certificatesResolver を、他の router に file プロバイダーの証明書を使えます。リクエストごとに、SNI による明示的な tls.certificates のマッチが、そのホスト名に対する ACME より優先されます。
Kubernetes では証明書をどこに置きますか?
file プロバイダーではありません。Kubernetes では証明書を TLS Secrets として用意し、IngressRoute/Ingress から参照します。このガイドの file プロバイダー方式は、Docker およびスタンドアロン(非 K8s)構成向けです。
Traefik は私のカスタム証明書を自動更新しますか?
いいえ。自動更新は Traefik が ACME を介して自分で発行する証明書にのみ適用されます。自前の証明書ではファイルを差し替えますが、--providers.file.watch=true のおかげで Traefik はダウンタイムなしでホットリロードします。これは上記の更新の方法セクションで説明したとおりです。
これは ECDSA/ECC 証明書でも動作しますか?
はい。Traefik は ECDSA 証明書を RSA とまったく同じように配信します — certFile/keyFile の設定も同じです。GetHTTPS はより小さく高速なハンドシェイクのため、デフォルトで ECDSA P-256 を発行します。