fbae2251e1
Closes #23637
225 lines
10 KiB
Text
225 lines
10 KiB
Text
<#import "/templates/guide.adoc" as tmpl>
|
|
<#import "/templates/kc.adoc" as kc>
|
|
<#import "/templates/options.adoc" as opts>
|
|
<#import "/templates/links.adoc" as links>
|
|
|
|
<@tmpl.guide
|
|
title="Running Keycloak in a container"
|
|
summary="Learn how to run Keycloak from a container image"
|
|
includedOptions="db db-url db-username db-password features hostname https-key-store-file https-key-store-password health-enabled metrics-enabled">
|
|
|
|
Keycloak handles containerized environments such as Kubernetes or OpenShift as first-class citizens. This {section} describes how to optimize and run the Keycloak container image to provide the best experience running a Keycloak container.
|
|
|
|
== Creating a customized and optimized container image
|
|
The default Keycloak container image ships ready to be configured and optimized.
|
|
|
|
For the best start up of your Keycloak container, build an image by running the `build` step during the container build.
|
|
This step will save time in every subsequent start phase of the container image.
|
|
|
|
=== Writing your optimized Keycloak Dockerfile
|
|
The following `Dockerfile` creates a pre-configured Keycloak image that enables the health and metrics endpoints, enables the token exchange feature, and uses a PostgreSQL database.
|
|
|
|
.Dockerfile:
|
|
[source, dockerfile]
|
|
----
|
|
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"]
|
|
----
|
|
The build process includes multiple stages:
|
|
|
|
* Run the `build` command to set server build options to create an optimized image.
|
|
* The files generated by the `build` stage are copied into a new image.
|
|
* In the final image, additional configuration options for the hostname and database are set so that you don't need to set them again when running the container.
|
|
* In the entrypoint, the `kc.sh` enables access to all the distribution sub-commands.
|
|
|
|
To install custom providers, you just need to define a step to include the JAR file(s) into the `/opt/keycloak/providers` directory.
|
|
This step must be placed before the line that `RUNs` the `build` command, as below:
|
|
|
|
[source, dockerfile]
|
|
----
|
|
# 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 <MY_PROVIDER_JAR_URL> /opt/keycloak/providers/myprovider.jar
|
|
|
|
...
|
|
|
|
# Context: RUN the build command
|
|
RUN /opt/keycloak/bin/kc.sh build
|
|
----
|
|
|
|
=== Installing additional RPM packages
|
|
|
|
If you try to install new software in a stage `+FROM quay.io/keycloak/keycloak+`, you will notice that `+microdnf+`, `+dnf+`, and even `+rpm+` are not installed. Also, very few packages are available, only enough for a `+bash+` shell, and to run Keycloak itself. This is due to security hardening measures, which reduce the attack surface of the Keycloak container.
|
|
|
|
First, consider if your use case can be implemented in a different way, and so avoid installing new RPMs into the final container:
|
|
|
|
* A `+RUN curl+` instruction in your Dockerfile can be replaced with `+ADD+`, since that instruction natively supports remote URLs.
|
|
* Some common CLI tools can be replaced by creative use of the Linux filesystem. For example, `+ip addr show tap0+` becomes `+cat /sys/class/net/tap0/address+`
|
|
* Tasks that need RPMs can be moved to a former stage of an image build, and the results copied across instead.
|
|
|
|
Here is an example. Running `+update-ca-trust+` in a former build stage, then copying the result forward:
|
|
|
|
[source, dockerfile]
|
|
----
|
|
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
|
|
----
|
|
|
|
It is possible to install new RPMs if absolutely required, following this two-stage pattern established by ubi-micro:
|
|
|
|
[source, dockerfile]
|
|
----
|
|
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 /
|
|
----
|
|
|
|
This approach uses a chroot, `+/mnt/rootfs+`, so that only the packages you specify and their dependencies are installed, and so can be easily copied into the second stage without guesswork.
|
|
|
|
WARNING: Some packages have a large tree of dependencies. By installing new RPMs you may unintentionally increase the container's attack surface. Check the list of installed packages carefully.
|
|
|
|
=== Building the docker image
|
|
To build the actual docker image, run the following command from the directory containing your Dockerfile:
|
|
|
|
[source,bash]
|
|
----
|
|
podman|docker build . -t mykeycloak
|
|
----
|
|
|
|
=== Starting the optimized Keycloak docker image
|
|
To start the image, run:
|
|
|
|
[source, bash]
|
|
----
|
|
podman|docker run --name mykeycloak -p 8443:8443 \
|
|
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=change_me \
|
|
mykeycloak \
|
|
start --optimized
|
|
----
|
|
|
|
Keycloak starts in production mode, using only secured HTTPS communication, and is available on `https://localhost:8443`.
|
|
|
|
Health check endpoints are available at `https://localhost:8443/health`, `https://localhost:8443/health/ready` and `https://localhost:8443/health/live`.
|
|
|
|
Opening up `https://localhost:8443/metrics` leads to a page containing operational metrics that could be used by your monitoring solution.
|
|
|
|
== Exposing the container to a different port
|
|
|
|
By default, the server is listening for `http` and `https` requests using the ports `8080` and `8443`, respectively.
|
|
|
|
If you want to expose the container using a different port, you need to set the `hostname-port` accordingly:
|
|
|
|
. Exposing the container using a port other than the default ports
|
|
[source, bash]
|
|
----
|
|
podman|docker run --name mykeycloak -p 3000:8443 \
|
|
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=change_me \
|
|
mykeycloak \
|
|
start --optimized --hostname-port=3000
|
|
----
|
|
|
|
By setting the `hostname-port` option you can now access the server at `https://localhost:3000`.
|
|
|
|
== Trying Keycloak in development mode
|
|
The easiest way to try Keycloak from a container for development or testing purposes is to use the Development mode.
|
|
You use the `start-dev` command:
|
|
|
|
[source,bash]
|
|
----
|
|
podman|docker run --name mykeycloak -p 8080:8080 \
|
|
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=change_me \
|
|
quay.io/keycloak/keycloak:latest \
|
|
start-dev
|
|
----
|
|
|
|
Invoking this command starts the Keycloak server in development mode.
|
|
|
|
This mode should be strictly avoided in production environments because it has insecure defaults.
|
|
For more information about running Keycloak in production, see <@links.server id="configuration-production"/>.
|
|
|
|
== Running a standard keycloak container
|
|
In keeping with concepts such as immutable infrastructure, containers need to be re-provisioned routinely.
|
|
In these environments, you need containers that start fast, therefore you need to create an optimized image as described in the preceding section.
|
|
However, if your environment has different requirements, you can run a standard Keycloak image by just running the `start` command.
|
|
For example:
|
|
|
|
[source, bash]
|
|
----
|
|
podman|docker run --name mykeycloak -p 8080:8080 \
|
|
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_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>
|
|
----
|
|
|
|
Running this command starts a Keycloak server that detects and applies the build options first.
|
|
In the example, the line `--db=postgres --features=token-exchange` sets the database vendor to PostgreSQL and enables the token exchange feature.
|
|
|
|
Keycloak then starts up and applies the configuration for the specific environment.
|
|
This approach significantly increases startup time and creates an image that is mutable, which is not the best practice.
|
|
|
|
== Provide initial admin credentials when running in a container
|
|
Keycloak only allows to create the initial admin user from a local network connection. This is not the case when running in a container, so you have to provide the following environment variables when you run the image:
|
|
|
|
[source, bash]
|
|
----
|
|
# setting the admin username
|
|
-e KEYCLOAK_ADMIN=<admin-user-name>
|
|
|
|
# setting the initial password
|
|
-e KEYCLOAK_ADMIN_PASSWORD=change_me
|
|
----
|
|
|
|
== Importing A Realm On Startup
|
|
|
|
The https://quay.io/keycloak/keycloak[published Keycloak containers] have a directory `/opt/keycloak/data/import`. If you put one or more import files in that directory via a volume mount or other means and add the startup argument `--import-realm`, the Keycloak container will import that data on startup! This may only make sense to do in Dev mode.
|
|
|
|
[source, bash]
|
|
----
|
|
podman|docker run --name keycloak_unoptimized -p 8080:8080 \
|
|
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=change_me \
|
|
-v /path/to/realm/data:/opt/keycloak/data/import \
|
|
quay.io/keycloak/keycloak:latest \
|
|
start-dev --import-realm
|
|
----
|
|
|
|
Feel free to join the open https://github.com/keycloak/keycloak/discussions/8549[GitHub Discussion] around enhancements of the admin bootstrapping process.
|
|
|
|
</@tmpl.guide>
|