Quarkus版Keycloakでは、起動前にビルドで焼き込む設定と、起動時に渡す設定が明確に分かれています。この分離を理解しないと、起動が遅い・機密が漏れる・本番でビルドが走るといった落とし穴にはまります。build-time optionとruntime optionの境界、--optimized起動、コンテナでのビルド戦略を実務目線で整理します。
Quarkus版のKeycloak(現行ディストリビューション)を触りはじめて最初に戸惑うのが、「なぜこの設定は起動時に効かないのか」という点です。WildFly版の感覚のまま start に全部のオプションを渡すと、警告が出たり無視されたりします。原因は、Quarkus版が設定をbuild-time option(ビルド時)とruntime option(起動時)の2階層に分けているからです。本稿ではこの分離を、現場でハマりやすいポイントとともに整理します。なお具体的なオプションの build/runtime 区分はバージョンで変わり得るため、新しめのバージョンを基準にしつつ最終的には公式ドキュメントでの確認を前提としてください。
01なぜ2階層に分かれるのか
Quarkus版は、起動時のオーバーヘッドを削るために「クローズドワールド仮定」で最適化します。インストールされているプロバイダやフィーチャーが起動のたびに変わらない、という前提を置くことで、プロバイダレジストリの再構築やファクトリ初期化を毎回やらずに済ませ、設定ファイルも事前パースしておく。これが kc.sh build の役割です。公式ドキュメントでも、Keycloakは「build コマンドで使えるbuild option」と「起動時に使えるconfiguration option」を区別すると明記されています(Configuring Keycloak)。
つまり、どのDBベンダーを使うか・どのフィーチャーを有効にするか、といった「サーバの骨格を決める設定」はビルド時に固め、URLやパスワードやホスト名のように「環境ごとに変わる設定」は起動時に渡す、という設計思想です。
02build時に焼き込む代表項目
ビルド時に確定させる代表的なオプションは次のとおりです。いずれも「有効/無効」や「どの実装を使うか」というサーバ構成そのものに関わる項目です。
db(データベースベンダー): postgres / mariadb / mssql など。どのJDBCドライバとダイアレクトを組み込むかがビルド時に決まります。接続URL・ユーザー・パスワードはビルド時ではなく起動時に渡します。features/features-disabled: 有効化するフィーチャー(preview含む)の集合。どのSPIやエンドポイントを組み込むかがここで確定します。health-enabled:/health系エンドポイントの有効化。metrics-enabled: Micrometer/Prometheus向けメトリクスの有効化。cache(local / ispn): Infinispanの動作モード。HA構成の土台になる項目です。transaction-xa-enabledなど、トランザクションマネージャの選択に関わる項目。
--metrics-enabled=true を渡したのにメトリクスが出ない」という問い合わせは定番です。metrics-enabled と health-enabled はbuild-time扱いなので、ビルド時に焼き込んでいなければ起動時指定は効きません。監視要件は設計フェーズで確定させ、イメージに含めておくのが鉄則です。03runtime時に渡す代表項目
一方、環境依存で毎回変わる値は起動時に渡します。むしろビルド時に入れてはいけないものが含まれる点が重要です。
- DB接続情報:
db-url/db-username/db-password。 - ホスト名関連:
hostnameほか、公開URLに関わる項目。 - TLS/証明書、プロキシ設定、ログレベルなど。
ここで見落としてはいけないのが機密の扱いです。公式ドキュメントは「すべてのbuild optionはプレーンテキストで永続化される。機密データをbuild optionとして保存してはならない」と明確に警告しています(Configuring Keycloak)。db-password をビルド時に渡すと、最適化されたイメージ内に平文で焼き込まれてしまいます。パスワードやシークレットは必ず起動時に、環境変数やシークレットマウント経由で供給してください。
04--optimized起動でビルドをスキップする
Quarkus版の start は、明示的にビルド済みでない場合、起動時に自動でビルド相当の処理を走らせます。これが本番で数十秒の起動遅延やコンテナのスケールアウト遅れの原因になります。事前に kc.sh build を済ませているなら、起動時に --optimized を付けます。
bin/kc.sh build --db=postgres --features=... --health-enabled=true --metrics-enabled=truebin/kc.sh start --optimized --db-url=... --db-username=... --hostname=...
--optimized は「すでに最適化済みのイメージを使う」とKeycloakに伝えるフラグで、起動時のビルドチェック・ビルド実行を回避して起動時間を短縮します(Configuring Keycloak)。
--optimized を付けたら、起動コマンドからはbuild-timeオプション(--db= や --features= など)を外し、runtimeオプションだけを残すのが正しい使い方です。両方を混在させると設定の出どころが二重化し、レビュー時に「どちらが効いているのか」が追いにくくなります。ビルド時と起動時でオプションの棚卸しを分けておくと、変更管理・統制の観点でもクリーンになります。05コンテナでのビルド戦略(マルチステージ)
本番はほぼコンテナ運用になるため、ビルドをどこで走らせるかが設計上の分かれ目です。推奨は、コンテナのイメージビルド時に kc.sh build を走らせるマルチステージ構成です。公式ドキュメントでも、ビルドステップをコンテナビルド時に実行することで「以降の毎回の起動フェーズで時間を節約できる」としています(Running Keycloak in a container)。
典型的な骨子は次の形です(バージョンで細部は変わるため公式のContainerfile例を基準に)。
- builderステージ: ベースイメージに対し
ENV KC_DB=postgres/ENV KC_HEALTH_ENABLED=true/ENV KC_METRICS_ENABLED=trueなどbuild-time項目を環境変数で与え、RUN /opt/keycloak/bin/kc.sh buildを実行。 - 最終ステージ: 新しいベースイメージに
COPY --from=builder /opt/keycloak/ /opt/keycloak/でビルド成果物をコピー。エントリポイントはkc.shのまま。
ここで重要なのが順序です。カスタムプロバイダ(SPIのJAR)を /opt/keycloak/providers に配置する場合、そのCOPYはbuildコマンドの前に置かなければなりません。公式も「このステップはbuildコマンドをRUNする行より前に置く必要がある」と明記しています(Running Keycloak in a container)。JARを後から入れてもクローズドワールドのレジストリには反映されず、プロバイダが認識されません。
06設計・統制の観点で効いてくる分離
この分離は単なる起動高速化テクニックではなく、変更管理と監査の観点でも効いてきます。build-time optionはイメージに紐づく=バージョン管理・ビルドパイプラインの対象、runtime optionはデプロイ環境に紐づく=シークレットマネージャや構成管理の対象、と責務がきれいに分かれます。
- 「どのフィーチャーを有効にしたイメージか」はイメージタグとビルド定義で追える。監査時にimmutableな根拠になります。
- 機密はイメージに入らないため、レジストリからの流出リスクを構造的に減らせます(平文永続化の警告に沿った運用)。
- 環境ごと(dev/stg/prod)に同一イメージを使い回し、runtimeオプションだけを差し替えるデプロイが自然に実現します。
マルチアカウント・マルチ環境で認証基盤を横断展開する場合、この「イメージは共通・環境設定は外出し」という原則がガバナンスの土台になります。統制の考え方はマルチアカウント統制とも通じます。WildFly版からの移行を検討中なら、この設定モデルの違いは最初に押さえるべきポイントです。
--server-async-bootstrap やヘルスチェックパス(/health/ready)の扱いも合わせて確認しておくと、K8sのreadinessプローブ設計まで一気通貫で決められます(Configuring Keycloak for production)。07ハマりどころチェックリスト
- 起動時にbuild-timeオプションを渡して「効かない」と悩む → build時に焼き込んだか確認。
db-passwordをビルド時に渡してイメージに平文が残る → 起動時供給に修正。--optimizedなしで本番起動し、毎回ビルドが走って遅い → ビルド済みイメージ+--optimizedへ。- プロバイダJARをbuildの後にCOPYして認識されない → 順序を修正。
- build/runtimeの区分を記憶で判断 → All configuration でbuild optionマークを都度確認。バージョンで区分が動くことがあります。
EMWではKeycloakによるエンタープライズ認証基盤の実構築で、この設定分離を前提にしたコンテナビルドパイプラインとデプロイ設計を組んできました。具体的な構成は導入事例もあわせてご覧ください。
—まとめ
Quarkus版Keycloakのbuild/runtime分離は、「サーバの骨格(db・features・health・metrics・cache)はビルドで固め、環境依存値と機密は起動時に渡す」という一本の原則に集約されます。kc.sh build でイメージを最適化し、マルチステージでビルドを前倒しし、--optimized で起動する。この型を守るだけで、起動速度・セキュリティ・統制のすべてが同時に整います。バージョンごとの区分は公式ドキュメントで最終確認する、という運用姿勢だけは崩さないでください。
—参考(一次情報)
- Configuring Keycloak — Keycloak (build option / configuration option の区別、--optimized、build optionの平文永続化警告)
- Running Keycloak in a container — Keycloak (マルチステージbuild、プロバイダJARの配置順、KC_DB/KC_HEALTH_ENABLED/KC_METRICS_ENABLED)
- Configuring Keycloak for production — Keycloak (本番設定、health/ready、features)
- All configuration — Keycloak (全設定リファレンス)