在容器中运行 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` 目录中。此步骤必须放在 `RUN` 构建命令之前的行,如下所示

# 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` 阶段安装新软件,您会注意到 `microdnf`、`dnf` 甚至 `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

如果绝对需要,可以按照 ubi-micro 建立的这种两阶段模式安装新的 RPM

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 通信,并且在 `http://127.0.0.1:8443` 上可用。

健康检查端点在 `http://127.0.0.1:9000/health`、`http://127.0.0.1:9000/health/ready` 和 `http://127.0.0.1:9000/health/live` 上可用。

打开 `http://127.0.0.1:9000/metrics` 将跳转到一个包含操作指标的页面,这些指标可供您的监控解决方案使用。

将容器公开到不同的端口

默认情况下,服务器使用端口 `8080` 和 `8443` 监听 `http` 和 `https` 请求。

如果要使用其他端口公开容器,则需要相应地设置 `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=http://127.0.0.1:3000

通过将 `hostname` 选项设置为完整 URL,您现在可以在 `http://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

在启动时导入领域

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.sh` 或 `kc.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

数据库供应商。

CLI: --db
Env: KC_DB

dev-file (默认值)、dev-memmariadbmssqlmysqloraclepostgres

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]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]kerberos[:v1]login[:v2,v1]multi-site[:v1]oid4vc-vci[:v1]opentelemetry[:v1]organization[:v1]par[:v1]passkeys[:v1]persistent-user-sessions[:v1]previewrecovery-codes[:v1]scripts[:v1]step-up-authentication[:v1]token-exchange[:v1]transient-users[:v1]update-email[: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

truefalse (默认值)

metrics-enabled

服务器是否应该公开指标。

如果启用,指标在 `metrics` 端点上可用。

CLI: --metrics-enabled
Env: KC_METRICS_ENABLED

truefalse (默认值)

在此页面上