Fedora Server上のPodmanでTraefik v3を構築する手順:SSL自動化と動的ルーティング

Fedora tutorial - IT technology blog
Fedora tutorial - IT technology blog

社内のマイクロサービス約20個をDocker SwarmからPodmanが稼働するFedora Serverへ移行した際、最大の障壁となったのがNginxの設定管理でした。新しいコンテナを立ち上げるたびに、nginx.confを開き、upstreamブロックを追記し、サービスをリロードしてCertbotでSSL証明書を取得するという作業を繰り返す必要がありました。セミコロンを1つ打ち間違えるだけでプロキシ全体が停止してしまいます。Traefikはこの煩雑さを根本から解消してくれます。Podmanのソケットからイベントを自動検出し、コンテナのラベル経由でルーティングを行い、Let’s Encryptの証明書も全自動で取得・更新します。

FedoraはRed Hatによって最新カーネルがいち早く提供され、cgroups v2とも緊密に統合されているため、Podmanを運用する上で理想的な環境です。Fedora 39/40上でTraefik v3とPodmanを組み合わせることで、軽量かつ安定稼働し、メンテナンス工数を劇的に削減できるプロキシ環境が実現します。

クイックスタート(5分でデプロイ)

事前にドメインのA/AAAAレコードをFedoraサーバーのIPアドレスに向けておき、ファイアウォールでポート80および443を開放しておきます。

sudo firewall-cmd --permanent --add-port={80,443}/tcp
sudo firewall-cmd --reload

1. Podman System Socketの有効化

TraefikはDocker API互換ソケット経由でPodmanと通信します。systemdレベルのソケットを有効化しましょう。

sudo systemctl enable --now podman.socket
# ソケットの稼働確認
curl -s --unix-socket /run/podman/podman.sock http://d/v1.41/version | jq .Version

2. Traefik用ディレクトリと設定ファイルの作成

設定ファイルと証明書保存用ファイル用のディレクトリを /opt/traefik に作成します。

sudo mkdir -p /opt/traefik
cd /opt/traefik
sudo touch acme.json
sudo chmod 600 acme.json

静的設定ファイル traefik.yml を作成します。

api:
  dashboard: true
  insecure: false

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false

certificatesResolvers:
  letsencrypt:
    acme:
      email: "[email protected]"
      storage: "/acme.json"
      httpChallenge:
        entryPoint: web

注意:証明書の期限切れ通知を受け取るため、[email protected] は実際のメールアドレスに置き換えてください。

3. Podman ComposeによるTraefikの起動

/opt/traefik/compose.yml を作成します。

version: "3.8"

services:
  traefik:
    image: docker.io/library/traefik:v3.0
    container_name: traefik
    restart: always
    ports:
      - "80:80"
      - "443:443"
    security_opt:
      - label=disable
    volumes:
      - /run/podman/podman.sock:/var/run/docker.sock:ro
      - /opt/traefik/traefik.yml:/traefik.yml:ro,z
      - /opt/traefik/acme.json:/acme.json:z
    networks:
      - proxy-net

networks:
  proxy-net:
    name: proxy-net

Traefikコンテナを起動します。

podman compose up -d

4. SSL対応テスト用アプリケーションの起動

自動証明書発行の動作を確認するため、軽量なNginx Webサーバーを立ち上げます。

podman run -d --name demo-web \
  --network proxy-net \
  --label "traefik.enable=true" \
  --label "traefik.http.routers.demo.rule=Host(\`app.example.com\`)" \
  --label "traefik.http.routers.demo.entrypoints=websecure" \
  --label "traefik.http.routers.demo.tls.certresolver=letsencrypt" \
  --label "traefik.http.services.demo.loadbalancer.server.port=80" \
  docker.io/library/nginx:alpine

ブラウザから https://app.example.com にアクセスします。ホスト側でNginxの設定を1行も書くことなく、わずか3〜5秒ほどで有効なHTTPS接続が確立されていることが確認できます。

理解しておくべき技術的仕組み

プロバイダー機構とDocker API互換性

Traefikはコンテナを定期的にポーリングするわけではありません。代わりに、podman.socket からのイベントストリームを直接リッスンします。

podman run を実行したりコンテナを停止したりすると、Traefikは即座にそのシグナルを検知します。メモリ上のルーティングテーブルは10ミリ秒未満で再構築されます。この処理はすべてバックグラウンドでシームレスに行われ、プロセスのリロードも発生せず、既存のTCP接続が切断されることもありません。

PodmanがUnixソケット経由でDocker標準APIを提供しているため、Traefikは外部プラグインを追加することなく、組み込みの docker プロバイダーをそのまま利用できます。

Fedora ServerにおけるSELinuxの壁と対処法

FedoraではSELinuxがデフォルトで Enforcing(強制)モードに設定されています。適切なセキュリティコンテキストを付与せずにファイルやソケットをマウントすると、コンテナは即座に Permission Denied エラーで失敗します。

押さえておくべき重要ポイントは以下の通りです。

  • ボリュームの :z フラグは、設定ファイル traefik.yml および acme.json に共有SELinuxラベル(共有コンテキスト container_file_t)を付与します。
  • システムソケットである /run/podman/podman.sock に対しては、絶対に :z フラグを使用してはいけません。システムソケットのラベルを書き換えると、systemdの権限エラーを引き起こす恐れがあります。代わりに、security_opt: ["label=disable"] オプションを指定して、Traefikコンテナ単体のラベル制限を無効化します。

Let’s Encrypt SSL証明書発行のライフサイクル

ポート443経由でドメイン app.example.com へ最初のリクエストが到達した際の流れは次の通りです。

  1. Traefikが acme.json ファイルを確認します。
  2. 証明書が存在しない場合、TraefikのACMEクライアントがLet’s Encryptへ新規発行リクエストを送信します。
  3. Let’s Encryptがポート80に HTTP-01 チャレンジを送信します。Traefikはこのリクエストのみを迎撃し、適切な認証トークンを返答します。
  4. 認証成功後、Let’s Encryptから証明書ペアと秘密鍵(private key)が発行されます。
  5. Traefikはそれらの情報を acme.json に保存し、即座にメモリへ展開します。証明書の有効期限が30日未満になると、Traefikが自動で定期更新を行います。

応用設定

1. Basic認証によるTraefikダッシュボードの保護

デフォルトでダッシュボードの公開設定は無効化されています(insecure: false)。専用のサブドメイン(例:traefik.example.com)経由で安全にダッシュボードへアクセスするには、認証ミドルウェアを挟んで内部サービス api@internal にルーターを接続します。

# パスワードハッシュの生成(インストール:sudo dnf install -y httpd-tools)
htpasswd -nb admin MatKhauManh_2026@Secure

compose.yml のTraefikサービスに以下のラベルを追加します。

    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
      - "traefik.http.routers.dashboard.middlewares=auth"
      - "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xyz...上記で生成したハッシュ文字列"

注意:Composeファイル内では、環境変数として誤展開されるのを防ぐため、ハッシュ化パスワード内のすべての $ を $$ とエスケープ表記する必要があります。

2. DNS-01チャレンジ(Cloudflare)によるワイルドカード証明書の発行

HTTP-01方式には、*.example.com のようなワイルドカード証明書が取得できない点や、サーバーのポート80をインターネットに公開しなければならないという制限があります。内部向けサービスにはDNSチャレンジの利用が最適です。

# traefik.ymlへの追記
certificatesResolvers:
  dns-cloudflare:
    acme:
      email: "[email protected]"
      storage: "/acme.json"
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "8.8.8.8:53"

TraefikのComposeファイルにCloudflareのAPIトークンを環境変数として追加します。

    environment:
      - CF_DNS_API_TOKEN=vj98aX_example_cloudflare_token

本番運用の実践ノウハウ・注意点

トラブルを未然に防ぐために押さえておくべき重要な運用ポイントです。

  • acme.json のパーミッション設定: Traefikは、このファイルのパーミッションが 600 以外に設定されていると即座に起動を停止します。誤って chmod で 644 に変更してしまったり別マシンから上書きコピーしたりすると、Traefikは permissions 0644 for /acme.json are too open というエラーを出力します。
  • Let’s Encryptのレート制限への注意: 設定テストを行う際は、caServer: "https://acme-staging-v02.api.letsencrypt.org/directory" を追記してステージングサーバーに向けてテストしてください。Let’s Encryptには1アカウント・ホスト名あたり1時間に5回までの失敗上限が設けられています。これを超えるとIPアドレスからの証明書発行が一時的にブロックされます。
  • トラブルシュートを容易にするJSON形式のアクセスログ有効化: 設定ファイルに accessLog: { format: json } を追加します。JSON形式にしておけば、Fluent BitやPromtailを経由してGrafana Lokiへ直接ログを転送・フィルタリングでき、アップストリームの応答時間や各コンテナのHTTPステータスを容易に可視化できます。
  • ネットワークの不一致による404エラー: ラベル設定後に404エラーが発生する原因の9割は、アプリケーションコンテナがTraefikと同じ proxy-net ネットワークに参加していないことです。Podmanのデフォルトブリッジネットワークではコンテナ間の名前解決が自動で行われないため注意が必要です。
Share: