在容器中运行 Keycloak

了解如何从容器镜像运行 Keycloak

本指南介绍如何优化和运行 Keycloak 容器镜像,以提供最佳的容器运行体验。

创建自定义和优化的容器镜像

默认的 Keycloak 容器镜像已准备好进行配置和优化。

为了获得最佳的 Keycloak 容器启动体验,请在容器构建期间运行 build 步骤来构建镜像。此步骤将节省容器镜像后续每次启动阶段的时间。

编写优化的 Keycloak Containerfile

以下 Containerfile 创建了一个预配置的 Keycloak 镜像,该镜像启用了健康和指标端点,启用了令牌交换功能,并使用了 PostgreSQL 数据库。

Containerfile
FROM quay.io/keycloak/keycloak:latest AS builder

# Enable health and metrics support
ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true

# Configure a database vendor
ENV KC_DB=postgres

WORKDIR /opt/keycloak
# for demonstration purposes only, please make sure to use proper certificates in production instead
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:latest
COPY --from=builder /opt/keycloak/ /opt/keycloak/

# change these values to point to a running postgres instance
ENV KC_DB=postgres
ENV KC_DB_URL=<DBURL>
ENV KC_DB_USERNAME=<DBUSERNAME>
ENV KC_DB_PASSWORD=<DBPASSWORD>
ENV KC_HOSTNAME=localhost
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

构建过程包括多个阶段

  • 运行 build 命令以设置服务器构建选项,从而创建优化的镜像。

  • build 阶段生成的文件被复制到一个新镜像中。

  • 在最终镜像中,设置了主机名和数据库的其他配置选项,这样您在运行容器时就不需要再次设置它们。

  • 在入口点,kc.sh 允许访问所有分发子命令。

要安装自定义提供程序,您只需要定义一个步骤,将 JAR 文件包含到 /opt/keycloak/providers 目录中。此步骤必须放在 RUNs build 命令的行之前,如下所示

# A example build step that downloads a JAR file from a URL and adds it to the providers directory
FROM quay.io/keycloak/keycloak:latest as builder

...

# Add the provider JAR file to the providers directory
ADD --chown=keycloak:keycloak --chmod=644 <MY_PROVIDER_JAR_URL> /opt/keycloak/providers/myprovider.jar

...

# Context: RUN the build command
RUN /opt/keycloak/bin/kc.sh build

安装额外的 RPM 包

如果您尝试在 FROM quay.io/keycloak/keycloak 阶段安装新软件,您会注意到 microdnfdnf 甚至 rpm 都没有安装。此外,只有极少的软件包可用,仅足以运行 bash shell 和 Keycloak 本身。这是由于安全强化措施,这些措施减少了 Keycloak 容器的攻击面。

首先,考虑您的用例是否可以用不同的方式实现,从而避免在最终容器中安装新的 RPM。

  • 您 Containerfile 中的 RUN curl 指令可以用 ADD 替换,因为该指令原生支持远程 URL。

  • 一些常用的 CLI 工具可以用创造性地使用 Linux 文件系统来代替。例如,ip addr show tap0 变为 cat /sys/class/net/tap0/address

  • 需要 RPM 的任务可以移动到镜像构建的前一个阶段,并将结果复制过来。

这是一个例子。在前一个构建阶段运行 update-ca-trust,然后将结果向前复制

FROM registry.access.redhat.com/ubi9 AS ubi-micro-build
COPY mycertificate.crt /etc/pki/ca-trust/source/anchors/mycertificate.crt
RUN update-ca-trust

FROM quay.io/keycloak/keycloak
COPY --from=ubi-micro-build /etc/pki /etc/pki

如果绝对需要安装新的 RPM,可以按照 ubi-micro 建立的两阶段模式进行操作。

FROM registry.access.redhat.com/ubi9 AS ubi-micro-build
RUN mkdir -p /mnt/rootfs
RUN dnf install --installroot /mnt/rootfs <package names go here> --releasever 9 --setopt install_weak_deps=false --nodocs -y && \
    dnf --installroot /mnt/rootfs clean all && \
    rpm --root /mnt/rootfs -e --nodeps setup

FROM quay.io/keycloak/keycloak
COPY --from=ubi-micro-build /mnt/rootfs /

这种方法使用 chroot,/mnt/rootfs,这样就只会安装您指定的软件包及其依赖项,从而可以轻松地复制到第二阶段,而无需猜测。

某些软件包具有庞大的依赖树。通过安装新的 RPM,您可能会无意中增加容器的攻击面。请仔细检查已安装软件包的列表。

构建容器镜像

要构建实际的容器镜像,请从包含您的 Containerfile 的目录运行以下命令

podman|docker build . -t mykeycloak

启动优化的 Keycloak 容器镜像

要启动镜像,请运行

podman|docker run --name mykeycloak -p 8443:8443 -p 9000:9000 \
        -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=change_me \
        mykeycloak \
        start --optimized --hostname=localhost

Keycloak 在生产模式下启动,仅使用安全的 HTTPS 通信,并且在 https://127.0.0.1:8443 上可用。

打开 https://127.0.0.1:9000/metrics 会显示一个包含操作指标的页面,您的监控解决方案可以使用这些指标。

将容器暴露到不同的端口

默认情况下,服务器监听使用端口 80808443httphttps 请求。

如果您想使用不同的端口暴露容器,您需要相应地设置 hostname

  1. 使用非默认端口暴露容器

podman|docker run --name mykeycloak -p 3000:8443 \
        -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=change_me \
        mykeycloak \
        start --optimized --hostname=https://127.0.0.1:3000

通过将 hostname 选项设置为完整的 URL,您现在可以通过 https://127.0.0.1:3000 访问服务器。

尝试在开发模式下运行 Keycloak

从容器中尝试 Keycloak 进行开发或测试的最简单方法是使用开发模式。您可以使用 start-dev 命令

podman|docker run --name mykeycloak -p 8080:8080 \
        -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=change_me \
        quay.io/keycloak/keycloak:latest \
        start-dev

调用此命令将在开发模式下启动 Keycloak 服务器。

在生产环境中应严格避免使用此模式,因为它具有不安全的默认设置。有关在生产环境中运行 Keycloak 的更多信息,请参阅 为生产环境配置 Keycloak

运行标准的 Keycloak 容器

为了与诸如不可变基础设施之类的概念保持一致,容器需要定期重新配置。在这些环境中,您需要启动速度快的容器,因此您需要创建如前节所述的优化镜像。但是,如果您的环境有不同的要求,您可以通过仅运行 start 命令来运行标准的 Keycloak 镜像。例如

podman|docker run --name mykeycloak -p 8080:8080 \
        -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=change_me \
        quay.io/keycloak/keycloak:latest \
        start \
        --db=postgres --features=token-exchange \
        --db-url=<JDBC-URL> --db-username=<DB-USER> --db-password=<DB-PASSWORD> \
        --https-key-store-file=<file> --https-key-store-password=<password>

运行此命令会启动一个 Keycloak 服务器,该服务器首先检测并应用构建选项。在示例中,行 --db=postgres --features=token-exchange 将数据库供应商设置为 PostgreSQL 并启用令牌交换功能。

然后 Keycloak 启动并应用特定环境的配置。这种方法会显著增加启动时间,并创建一个可变的镜像,这不是最佳实践。

在容器中运行时提供初始管理员凭据

Keycloak 仅允许从本地网络连接创建初始管理员用户。在容器中运行时并非如此,因此您必须在运行镜像时提供以下环境变量

# setting the admin username
-e KC_BOOTSTRAP_ADMIN_USERNAME=<admin-user-name>

# setting the initial password
-e KC_BOOTSTRAP_ADMIN_PASSWORD=change_me

在启动时导入 Realm

Keycloak 容器有一个目录 /opt/keycloak/data/import。如果您通过卷挂载或其他方式将一个或多个导入文件放入该目录,并添加启动参数 --import-realm,则 Keycloak 容器将在启动时导入该数据!这可能只在开发模式下有意义。

podman|docker run --name keycloak_unoptimized -p 8080:8080 \
        -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=change_me \
        -v /path/to/realm/data:/opt/keycloak/data/import \
        quay.io/keycloak/keycloak:latest \
        start-dev --import-realm

欢迎加入关于改进管理员引导过程的开放 GitHub 讨论

指定不同的内存设置

Keycloak 容器没有为初始和最大堆大小指定硬编码值,而是使用相对于容器总内存的相对值。此行为是通过 JVM 选项 -XX:MaxRAMPercentage=70-XX:InitialRAMPercentage=50 实现的。

-XX:MaxRAMPercentage 选项将最大堆大小表示为容器总内存的 70%。-XX:InitialRAMPercentage 选项将初始堆大小表示为容器总内存的 50%。这些值是基于对 Keycloak 内存管理的深入分析而选择的。

由于堆大小是根据容器总内存动态计算的,因此您应该始终为容器设置内存限制。以前,最大堆大小设置为 512 MB,为了接近类似的值,您应将内存限制设置为至少 750 MB。对于较小的生产就绪部署,建议的内存限制为 2 GB。

与堆相关的 JVM 选项可能会被设置环境变量 JAVA_OPTS_KC_HEAP 覆盖。您可以在 kc.shkc.bat 脚本的源代码中找到 JAVA_OPTS_KC_HEAP 的默认值。

例如,您可以按如下方式指定环境变量和内存限制

podman|docker run --name mykeycloak -p 8080:8080 -m 1g \
        -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=change_me \
        -e JAVA_OPTS_KC_HEAP="-XX:MaxHeapFreeRatio=30 -XX:MaxRAMPercentage=65" \
        quay.io/keycloak/keycloak:latest \
        start-dev
如果未设置内存限制,则内存消耗会迅速增加,因为堆大小可以增长到容器总内存的 70%。一旦 JVM 分配了内存,根据当前的 Keycloak GC 设置,它会很不情愿地将内存返回给操作系统。

相关选项

db

数据库供应商。

在生产模式下,dev-file 的默认值已被弃用,您应该显式指定数据库。

CLI: --db
Env: KC_DB

dev-file (默认), dev-mem, mariadb, mssql, mysql, oracle, postgres

db-password

数据库用户的密码。

CLI: --db-password
Env: KC_DB_PASSWORD

db-url

完整的数据库 JDBC URL。

如果未提供,则会根据所选的数据库供应商设置默认 URL。例如,如果使用 postgres,则默认的 JDBC URL 将为 jdbc:postgresql://127.0.0.1/keycloak

CLI: --db-url
Env: KC_DB_URL

db-username

数据库用户的用户名。

CLI: --db-username
Env: KC_DB_USERNAME

features

启用一组或多个功能。

CLI: --features
Env: KC_FEATURES

account-api[:v1], account[:v3], admin-api[:v1], admin-fine-grained-authz[:v1,v2], admin[:v2], authorization[:v1], cache-embedded-remote-store[:v1], ciba[:v1], client-policies[:v1], client-secret-rotation[:v1], client-types[:v1], clusterless[:v1], declarative-ui[:v1], device-flow[:v1], docker[:v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v2], impersonation[:v1], ipa-tuura-federation[:v1], kerberos[:v1], login[:v2,v1], multi-site[:v1], oid4vc-vci[:v1], opentelemetry[:v1], organization[:v1], par[:v1], passkeys[:v1], persistent-user-sessions[:v1], preview, quick-theme[:v1], recovery-codes[:v1], rolling-updates[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange-standard[:v2], token-exchange[:v1], transient-users[:v1], update-email[:v1], user-event-metrics[:v1], web-authn[:v1]

hostname

服务器暴露的地址。

可以是完整的 URL,也可以只是主机名。当仅提供主机名时,方案、端口和上下文路径将从请求中解析。

CLI: --hostname
Env: KC_HOSTNAME

仅当启用 hostname:v2 功能时可用

https-key-store-file

保存证书信息的密钥库,而不是指定单独的文件。

CLI: --https-key-store-file
Env: KC_HTTPS_KEY_STORE_FILE

https-key-store-password

密钥库文件的密码。

CLI: --https-key-store-password
Env: KC_HTTPS_KEY_STORE_PASSWORD

password (默认)

health-enabled

服务器是否应暴露健康检查端点。

如果启用,则健康检查在 /health/health/ready/health/live 端点可用。

CLI: --health-enabled
Env: KC_HEALTH_ENABLED

true, false (默认)

metrics-enabled

服务器是否应暴露指标。

如果启用,则指标在 /metrics 端点可用。

CLI: --metrics-enabled
Env: KC_METRICS_ENABLED

true, false (默认)

在此页上