Setting Up a Keycloak Cluster with Docker Compose and JDBC-PING
Written on
In this guide, we will walk you through the process of configuring a Keycloak cluster locally with three instances, enabling distributed caching. This setup is particularly useful for developers who want to secure their applications using Keycloak and test the entire solution in a controlled local environment.
Keycloak is an open-source Identity and Access Management (IAM) solution that provides comprehensive user identity management, authentication, and authorization capabilities for applications.
Each Keycloak instance will run in its own Docker container, utilizing a MariaDB database for data storage. To streamline the setup and configuration of these containers, we will make use of Docker Compose. This tool simplifies the management of multi-container Docker applications through a YAML-based syntax that defines and configures the necessary containers, networks, and volumes for your application.
The distributed cache functionality in Keycloak is built on Infinispan, an open-source, distributed, in-memory key-value data store, which is designed for high scalability, availability, and fault tolerance.
When running Keycloak in development mode with the “start-dev” command, distributed caches are disabled. Conversely, in production mode with the “start” command, caching is activated, allowing automatic discovery of Keycloak instances on the network. By default, these caches employ a UDP transport stack for IP multicast-based instance discovery.
In this article, we will deviate from the default configuration by using JDBC-PING instead. JDBC-PING enables distributed caching in Keycloak by utilizing a JDBC-compatible database for storing and sharing cached data among multiple instances. For this purpose, we will use the MariaDB database to facilitate the JDBC-PING discovery protocol.
Since the official Keycloak Docker image does not directly support JDBC-PING, we will employ a custom Docker image named keycloak-clustered. This maintained image is based on the official Keycloak Docker image and includes a modified Infinispan configuration file to support the JDBC-PING discovery protocol. You can access the code for this custom image in the keycloak-clustered GitHub repository.
For a more in-depth understanding of the modifications made to the Infinispan configuration file for JDBC-PING support, I encourage you to read the supplementary article, which offers detailed insights on the subject.
Let’s get started!
Project Diagram
The visual representation of our desired project outcome.
Additional Readings
Keycloak Cluster Setup with Vagrant, Virtual Machines, and JDBC-PING for Distributed Caching
Step-by-step guide on how to use Vagrant to deploy and manage a cluster of three Keycloak instances.
(source: medium.com)
Keycloak Cluster Setup with Docker Compose and UDP for Distributed Caching
Step-by-step guide on how to use Docker Compose to start a cluster of three Keycloak Docker containers using UDP for distributed caching.
(source: medium.com)
Keycloak Cluster Setup with UDP for Distributed Caching in Minikube (Kubernetes)
Step-by-step guide on how to start a cluster of three Keycloak instances using UDP for distributed caching in Minikube.
(source: medium.com)
Prerequisites
To follow this guide, please ensure that you have Docker Desktop installed on your machine. You can find installation instructions for Mac, Windows, and Linux on the Docker Docs website.
Creating the Docker Compose File
Open your preferred text editor and create a file named docker-compose.yml with the following content:
version: '3.8'
services:
mariadb:
image: mariadb:10.11.4
container_name: mariadb
ports:
- "3306:3306"
environment:
- MARIADB_DATABASE=keycloak
- MARIADB_USER=keycloak
- MARIADB_PASSWORD=password
- MARIADB_ROOT_PASSWORD=root_password
keycloak-clustered-1:
image: ivanfranchin/keycloak-clustered:latest
container_name: keycloak-clustered-1
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin
- KC_DB=mariadb
- KC_DB_URL_HOST=mariadb
- KC_DB_URL_DATABASE=keycloak
- KC_DB_USERNAME=keycloak
- KC_DB_PASSWORD=password
- KC_HEALTH_ENABLED=true
- KC_LOG_LEVEL=INFO,org.infinispan:DEBUG,org.jgroups:DEBUG
- JGROUPS_DISCOVERY_EXTERNAL_IP=keycloak-clustered-1
ports:
- "8080:8080"
command: start-dev
depends_on:
- mariadb
keycloak-clustered-2:
image: ivanfranchin/keycloak-clustered:latest
container_name: keycloak-clustered-2
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin
- KC_DB=mariadb
- KC_DB_URL_HOST=mariadb
- KC_DB_URL_DATABASE=keycloak
- KC_DB_USERNAME=keycloak
- KC_DB_PASSWORD=password
- KC_HEALTH_ENABLED=true
- KC_LOG_LEVEL=INFO,org.infinispan:DEBUG,org.jgroups:DEBUG
- JGROUPS_DISCOVERY_EXTERNAL_IP=keycloak-clustered-2
ports:
- "8081:8080"
command: start-dev
depends_on:
- mariadb
keycloak-clustered-3:
image: ivanfranchin/keycloak-clustered:latest
container_name: keycloak-clustered-3
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin
- KC_DB=mariadb
- KC_DB_URL_HOST=mariadb
- KC_DB_URL_DATABASE=keycloak
- KC_DB_USERNAME=keycloak
- KC_DB_PASSWORD=password
- KC_HEALTH_ENABLED=true
- KC_LOG_LEVEL=INFO,org.infinispan:DEBUG,org.jgroups:DEBUG
- JGROUPS_DISCOVERY_EXTERNAL_IP=keycloak-clustered-3
ports:
- "8082:8080"
command: start-dev
depends_on:
- mariadb
Save the docker-compose.yml file in your preferred directory.
Starting the Cluster
Navigate to the folder containing your docker-compose.yml file and run the following command:
docker compose up -d
Executing this command will initiate the following processes:
- Docker Compose reads the configuration file (docker-compose.yml).
- Docker pulls the necessary container images if they are not already available.
- Containers for each service are created and started.
- The containers run in the background (detached mode).
- Networks are connected and ports are mapped as specified.
- Dependencies between services are managed automatically.
- You can interact with the services once they are running.
Demonstration
To verify that our Keycloak cluster is functioning correctly, follow these steps:
- Open three different browsers (e.g., Chrome, Safari, and Firefox) or use different profiles (e.g., Chrome, Incognito Chrome, and Firefox).
- Access the following URLs:
- http://localhost:8080/admin/ in one browser
- http://localhost:8081/admin/ in another
- http://localhost:8082/admin/ in the last one
- Log in to Keycloak using “admin” as both the username and password.
- In one of the browsers, click on “Sessions” in the left-side menu. You should see that the “admin” user has three active sessions.
- Sign out of Keycloak in one of the browsers.
- Check the session count for the “admin” user again; it should now show two active sessions.
By following these steps, you can assess the functionality of the Keycloak cluster and observe how session management operates for the “admin” user.
Troubleshooting
Check Keycloak Logs You can inspect the logs of the keycloak-clustered-1 container using the following command:
docker logs keycloak-clustered-1
Check JGROUPSPING Table To access the MariaDB Docker container’s terminal (MariaDB Monitor), run the following command:
docker exec -it mariadb mariadb -ukeycloak -ppassword --database keycloak
Within the MariaDB Monitor, execute the following SELECT command to view information about the Keycloak instances in the cluster:
SELECT * FROM JGROUPSPING;
This query should yield results similar to the following:
To exit the MariaDB Monitor, simply type “exit” and hit Enter.
Shutting Down the Cluster
Ensure that you are in the directory where you saved the docker-compose.yml file, and execute the following command:
docker compose down -v
Conclusion
In this tutorial, we demonstrated how to set up a Keycloak cluster with three instances for distributed caching. By using Docker and Docker Compose, we simplified the configuration of Keycloak instances across separate containers. The cluster leverages Infinispan for distributed caching, ensuring scalability and fault tolerance. For this demonstration, we employed a custom Keycloak Clustered Docker image and utilized the JDBC-PING discovery protocol.
Support and Engagement
If you found this article helpful and would like to support my work, consider taking the following actions:
- Engage by clapping, highlighting, and replying to my story. I’m here to answer any questions you may have.
- Share this story on social media.
- Follow me on: Medium | LinkedIn | Twitter.
- Subscribe to my newsletter to stay updated with my latest posts.