社内のマイクロサービス約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 へ最初のリクエストが到達した際の流れは次の通りです。
- Traefikが
acme.jsonファイルを確認します。 - 証明書が存在しない場合、TraefikのACMEクライアントがLet’s Encryptへ新規発行リクエストを送信します。
- Let’s Encryptがポート80に
HTTP-01チャレンジを送信します。Traefikはこのリクエストのみを迎撃し、適切な認証トークンを返答します。 - 認証成功後、Let’s Encryptから証明書ペアと秘密鍵(private key)が発行されます。
- 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のデフォルトブリッジネットワークではコンテナ間の名前解決が自動で行われないため注意が必要です。

