Running Keycloak in a container
Excerpt
Keycloak is an open source identity and access management solution
Keycloak handles containerized environments such as Kubernetes or OpenShift as first-class citizens. This guide 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.
Building your optimized Keycloak docker image
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:
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_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:
# A example build step that downloads a JAR file from a URL and adds it to the providers directory
RUN curl -sL <MY_PROVIDER_JAR_URL> -o /opt/keycloak/providers/myprovider.jar
Building the docker image
To build the actual docker image, run the following command from the directory containing your Dockerfile:
podman|docker build . -t mykeycloak
Starting the optimized Keycloak docker image
To start the image, run:
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](https://localhost:8443/)
.
Opening up [https://localhost:8443/metrics](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
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](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:
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, take a look at the Configuring Keycloak for production guide.
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:
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:
# 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 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.
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 GitHub Discussion around enhancements of the admin bootstrapping process.
Relevant options
db
The database vendor.
CLI: |
Env: |
db-password
The password of the database user.
CLI: |
Env: |
db-url
The full database JDBC URL.
If not provided, a default URL is set based on the selected database vendor. For instance, if using 'postgres', the default JDBC URL would be 'jdbc:postgresql://localhost/keycloak'. |
CLI: |
Env: |
db-username
The username of the database user.
CLI: |
Env: |
features
Enables a set of one or more features.
CLI: |
Env: |
values | default | build |
---|---|---|
authorization, account2, account-api, admin-fine-grained-authz, admin-api, admin, admin2, docker, impersonation, openshift-integration, scripts, token-exchange, web-authn, client-policies, ciba, map-storage, par, declarative-user-profile, dynamic-scopes, client-secret-rotation, step-up-authentication, recovery-codes, update-email, js-adapter, preview | true |
health-enabled
If the server should expose health check endpoints.
If enabled, health checks are available at the '/health', '/health/ready' and '/health/live' endpoints. |
CLI: |
Env: |
values | default | build |
---|---|---|
true, false | false | true |
hostname
Hostname for the Keycloak server.
CLI: |
Env: |
https-key-store-file
The key store which holds the certificate information instead of specifying separate files.
CLI: |
Env: |
https-key-store-password
The password of the key store file.
CLI: |
Env: |
metrics-enabled
If the server should expose metrics.
If enabled, metrics are available at the '/metrics' endpoint. |
CLI: |
Env: |
values | default | build |
---|---|---|
true, false | false | true |