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.
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.
* 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.
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
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
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.
Health check endpoints are available at `https://localhost:8443/health`, `https://localhost:8443/health/ready` and `https://localhost:8443/health/live`.
== 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:
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 \
Feel free to join the open https://github.com/keycloak/keycloak/discussions/8549[GitHub Discussion] around enhancements of the admin bootstrapping process.