2022-01-27 13:57:18 +00:00
<#import "/templates/guide.adoc" as tmpl>
<#import "/templates/kc.adoc" as kc>
<#import "/templates/options.adoc" as opts>
<#import "/templates/links.adoc" as links>
2023-10-10 17:22:29 +00:00
<#import "/templates/profile.adoc" as profile>
2022-01-27 13:57:18 +00:00
<@tmpl.guide
2023-11-08 14:09:04 +00:00
title="Running {project_name} in a container"
summary="Learn how to run {project_name} from a container image"
2022-02-22 15:49:39 +00:00
includedOptions="db db-url db-username db-password features hostname https-key-store-file https-key-store-password health-enabled metrics-enabled">
2022-01-27 13:57:18 +00:00
2024-03-15 18:26:53 +00:00
This {section} describes how to optimize and run the {project_name} container image to provide the best experience running a container.
2023-10-06 19:51:32 +00:00
<@profile.ifProduct>
2024-01-09 14:20:18 +00:00
WARNING: This chapter applies only for building an image that you run in a OpenShift environment. Only an OpenShift environment is supported for this image. It is not supported if you run it in other Kubernetes distributions.
2023-10-06 19:51:32 +00:00
</@profile.ifProduct>
2022-01-27 13:57:18 +00:00
2022-04-08 09:56:47 +00:00
== Creating a customized and optimized container image
2023-11-08 14:09:04 +00:00
The default {project_name} container image ships ready to be configured and optimized.
2022-04-08 09:56:47 +00:00
2023-11-08 14:09:04 +00:00
For the best start up of your {project_name} container, build an image by running the `build` step during the container build.
2022-04-08 09:56:47 +00:00
This step will save time in every subsequent start phase of the container image.
2022-01-27 13:57:18 +00:00
2023-11-08 14:09:04 +00:00
=== Writing your optimized {project_name} Dockerfile
The following `Dockerfile` creates a pre-configured {project_name} image that enables the health and metrics endpoints, enables the token exchange feature, and uses a PostgreSQL database.
2022-01-27 13:57:18 +00:00
.Dockerfile:
2024-02-06 11:12:11 +00:00
[source,dockerfile,subs="attributes+"]
2022-01-27 13:57:18 +00:00
----
2024-02-06 11:12:11 +00:00
FROM quay.io/keycloak/keycloak:{containerlabel} as builder
2022-01-27 13:57:18 +00:00
2022-08-05 11:52:10 +00:00
# Enable health and metrics support
2022-02-22 15:49:39 +00:00
ENV KC_HEALTH_ENABLED=true
2022-01-27 13:57:18 +00:00
ENV KC_METRICS_ENABLED=true
2022-08-05 11:52:10 +00:00
# Configure a database vendor
2022-01-27 13:57:18 +00:00
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
2022-08-05 11:52:10 +00:00
RUN /opt/keycloak/bin/kc.sh build
2024-02-06 11:12:11 +00:00
FROM quay.io/keycloak/keycloak:{containerlabel}
2022-08-05 11:52:10 +00:00
COPY --from=builder /opt/keycloak/ /opt/keycloak/
2022-01-27 13:57:18 +00:00
# change these values to point to a running postgres instance
2023-01-20 08:14:32 +00:00
ENV KC_DB=postgres
2022-01-27 13:57:18 +00:00
ENV KC_DB_URL=<DBURL>
ENV KC_DB_USERNAME=<DBUSERNAME>
ENV KC_DB_PASSWORD=<DBPASSWORD>
2022-04-07 06:07:12 +00:00
ENV KC_HOSTNAME=localhost
2022-05-05 14:16:01 +00:00
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
2022-01-27 13:57:18 +00:00
----
2022-02-02 07:43:35 +00:00
The build process includes multiple stages:
2022-01-27 13:57:18 +00:00
2022-08-05 11:52:10 +00:00
* Run the `build` command to set server build options to create an optimized image.
2022-04-08 09:56:47 +00:00
* The files generated by the `build` stage are copied into a new image.
2022-08-05 11:52:10 +00:00
* 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.
2022-05-05 15:00:30 +00:00
* In the entrypoint, the `kc.sh` enables access to all the distribution sub-commands.
2022-02-02 07:43:35 +00:00
2023-08-23 07:19:22 +00:00
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:
2022-04-08 09:56:47 +00:00
2024-02-06 11:12:11 +00:00
[source,dockerfile,subs="attributes+"]
2022-04-08 09:56:47 +00:00
----
2022-08-05 11:52:10 +00:00
# A example build step that downloads a JAR file from a URL and adds it to the providers directory
2024-02-06 11:12:11 +00:00
FROM quay.io/keycloak/keycloak:{containerlabel} as builder
2023-08-23 07:19:22 +00:00
...
# Add the provider JAR file to the providers directory
2023-03-09 15:12:42 +00:00
ADD --chown=keycloak:keycloak <MY_PROVIDER_JAR_URL> /opt/keycloak/providers/myprovider.jar
2023-08-23 07:19:22 +00:00
...
# Context: RUN the build command
RUN /opt/keycloak/bin/kc.sh build
2022-04-08 09:56:47 +00:00
----
2022-01-27 13:57:18 +00:00
2023-02-27 18:53:30 +00:00
=== Installing additional RPM packages
2024-03-15 18:26:53 +00:00
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 {project_name} itself. This is due to security hardening measures, which reduce the attack surface of the {project_name} container.
2023-02-27 18:53:30 +00:00
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
2023-10-03 07:06:55 +00:00
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
2023-02-27 18:53:30 +00:00
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.
2024-02-28 12:43:26 +00:00
=== Building the container image
To build the actual container image, run the following command from the directory containing your Dockerfile:
2022-02-02 07:43:35 +00:00
2022-01-27 13:57:18 +00:00
[source,bash]
----
2022-08-05 11:52:10 +00:00
podman|docker build . -t mykeycloak
2022-01-27 13:57:18 +00:00
----
2024-02-28 12:43:26 +00:00
=== Starting the optimized {project_name} container image
2022-01-27 13:57:18 +00:00
To start the image, run:
2022-08-05 11:52:10 +00:00
2022-01-27 13:57:18 +00:00
[source, bash]
----
2022-08-05 11:52:10 +00:00
podman|docker run --name mykeycloak -p 8443:8443 \
2022-05-05 14:16:01 +00:00
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=change_me \
2022-08-05 11:52:10 +00:00
mykeycloak \
2022-07-22 06:40:31 +00:00
start --optimized
2022-01-27 13:57:18 +00:00
----
2022-08-05 11:52:10 +00:00
2023-11-08 14:09:04 +00:00
{project_name} starts in production mode, using only secured HTTPS communication, and is available on `https://localhost:8443`.
2022-01-27 13:57:18 +00:00
2022-02-22 15:49:39 +00:00
Health check endpoints are available at `https://localhost:8443/health`, `https://localhost:8443/health/ready` and `https://localhost:8443/health/live`.
2022-02-02 07:43:35 +00:00
Opening up `https://localhost:8443/metrics` leads to a page containing operational metrics that could be used by your monitoring solution.
2022-01-27 13:57:18 +00:00
2022-08-05 11:52:10 +00:00
== 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`.
2023-11-08 14:09:04 +00:00
== Trying {project_name} in development mode
The easiest way to try {project_name} from a container for development or testing purposes is to use the Development mode.
2022-02-02 07:43:35 +00:00
You use the `start-dev` command:
2022-01-27 13:57:18 +00:00
2024-02-06 11:12:11 +00:00
[source,bash,subs="attributes+"]
2022-01-27 13:57:18 +00:00
----
2022-08-05 11:52:10 +00:00
podman|docker run --name mykeycloak -p 8080:8080 \
2022-01-27 13:57:18 +00:00
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=change_me \
2024-02-06 11:12:11 +00:00
quay.io/keycloak/keycloak:{containerlabel} \
2022-01-27 13:57:18 +00:00
start-dev
----
2023-11-08 14:09:04 +00:00
Invoking this command starts the {project_name} server in development mode.
2022-01-27 13:57:18 +00:00
2022-02-02 07:43:35 +00:00
This mode should be strictly avoided in production environments because it has insecure defaults.
2023-11-08 14:09:04 +00:00
For more information about running {project_name} in production, see <@links.server id="configuration-production"/>.
2022-01-27 13:57:18 +00:00
2023-11-08 14:09:04 +00:00
== Running a standard {project_name} container
2022-02-02 07:43:35 +00:00
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.
2023-11-08 14:09:04 +00:00
However, if your environment has different requirements, you can run a standard {project_name} image by just running the `start` command.
2022-02-02 07:43:35 +00:00
For example:
2022-01-27 13:57:18 +00:00
2024-02-06 11:12:11 +00:00
[source,bash,subs="attributes+"]
2022-01-27 13:57:18 +00:00
----
2022-08-05 11:52:10 +00:00
podman|docker run --name mykeycloak -p 8080:8080 \
2022-01-27 13:57:18 +00:00
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=change_me \
2024-02-06 11:12:11 +00:00
quay.io/keycloak/keycloak:{containerlabel} \
2022-01-27 13:57:18 +00:00
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>
----
2023-11-08 14:09:04 +00:00
Running this command starts a {project_name} server that detects and applies the build options first.
2022-02-02 07:43:35 +00:00
In the example, the line `--db=postgres --features=token-exchange` sets the database vendor to PostgreSQL and enables the token exchange feature.
2022-01-27 13:57:18 +00:00
2023-11-08 14:09:04 +00:00
{project_name} then starts up and applies the configuration for the specific environment.
2022-02-02 07:43:35 +00:00
This approach significantly increases startup time and creates an image that is mutable, which is not the best practice.
2022-01-27 13:57:18 +00:00
2022-02-24 17:00:32 +00:00
== Provide initial admin credentials when running in a container
2023-11-08 14:09:04 +00:00
{project_name} 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:
2022-02-24 17:00:32 +00:00
[source, bash]
----
# setting the admin username
-e KEYCLOAK_ADMIN=<admin-user-name>
# setting the initial password
-e KEYCLOAK_ADMIN_PASSWORD=change_me
----
2022-08-04 13:28:26 +00:00
== Importing A Realm On Startup
2024-03-15 18:26:53 +00:00
The {project_name} 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 {project_name} container will import that data on startup! This may only make sense to do in Dev mode.
2022-08-04 13:28:26 +00:00
2024-02-06 11:12:11 +00:00
[source,bash,subs="attributes+"]
2022-08-04 13:28:26 +00:00
----
podman|docker run --name keycloak_unoptimized -p 8080:8080 \
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=change_me \
2023-01-20 08:10:31 +00:00
-v /path/to/realm/data:/opt/keycloak/data/import \
2024-02-06 11:12:11 +00:00
quay.io/keycloak/keycloak:{containerlabel} \
2022-08-04 13:28:26 +00:00
start-dev --import-realm
----
2022-02-24 17:00:32 +00:00
Feel free to join the open https://github.com/keycloak/keycloak/discussions/8549[GitHub Discussion] around enhancements of the admin bootstrapping process.
2024-02-15 12:38:41 +00:00
== Specifying different memory settings
The {project_name} container, instead of specifying hardcoded values for the initial and maximum heap size, uses relative values to the total memory of a container.
This behavior is achieved by JVM options `-XX:MaxRAMPercentage=70`, and `-XX:InitialRAMPercentage=50`.
The `-XX:MaxRAMPercentage` option represents the maximum heap size as 70% of the total container memory.
The `-XX:InitialRAMPercentage` option represents the initial heap size as 50% of the total container memory.
2024-03-15 18:26:53 +00:00
These values were chosen based on a deeper analysis of {project_name} memory management.
2024-02-15 12:38:41 +00:00
The JVM options related to the heap might be overridden by setting the environment variable `JAVA_OPTS_KC_HEAP`.
You can find the default values of the `JAVA_OPTS_KC_HEAP` in the source code of the `kc.sh`, or `kc.bat` script.
For example, you can specify the environment variable as follows:
[source,bash,subs="attributes+"]
----
podman|docker run --name mykeycloak -p 8080:8080 \
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=change_me \
-e JAVA_OPTS_KC_HEAP="-XX:MaxHeapFreeRatio=30 -XX:MaxRAMPercentage=65" \
quay.io/keycloak/keycloak:{containerlabel} \
start-dev
----
2022-01-27 13:57:18 +00:00
</@tmpl.guide>