How to Setup Keycloak With MySQL Database using CLI in Docker

czetsuya
3 min readOct 9, 2022

1. Introduction

Keycloak is one of the most popular open-source Identity and Access Management platforms backed by RedHat. It is known for its flexibility and extensibility which makes it a top candidate in the enterprise world where there are complicated use cases for user authentication and authorization. For example, having multiple applications that must support multi-tenant and n-reseller levels with a single login.

1.1 Prerequisites

Knowledge of the following is required.

  • Keycloak
  • Docker
  • MySQL

2. ct-keycloak-iam

ct-keycloak-iam is a project I developed to deliver a custom Keycloak server in a docker container. It includes a default realm, custom themes, database connection (MySQL), and custom SPIs (required sponsorship).

It contains CLI scripts that will download the Keycloak server and install a MySQL data source.

The project is available at https://github.com/czetsuya/ct-keycloak-iam.

Folders/files that we will use.

  • keycloak-docker-assembly
  • docker
  • Dockerfile — builds a custom Keycloak container
  • docker-compose-dev.yml — builds and runs the custom Keycloak container and MySQL.
  • src/main/resources
  • build
  • cli/database/mysql
  • set-database.cli — a set of instructions to create an entry of MySQL data source and driver in your Keycloak configuration. Note that it uses the environment variables defined in your docker-compose file.
  • build-keycloak.sh
  • modules/databases/mysql
  • module.xml — MySQL module file needed by Keycloak, make sure that the version matches the one defined in the Dockerfile (instead you changed it)

3. Docker Compose

Instead of manually creating a MySQL database, users, and permissions we will use a MySQL docker image to do the job.

We need to define the MySQL connection settings as environment variables.

version: ‘3’

services:
keycloak-db:
image: mysql:8.0
ports:
— 33066:3306
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: keycloak
MYSQL_USER: keycloak
MYSQL_PASSWORD: keycloak
command: mysqld — sql_mode=””

ct-keycloak-iam:
depends_on:
— keycloak-db
build:
context: ../
dockerfile: docker/Dockerfile
ports:
— 8888:8888
— 8080:8080
— 8443:8443
— 9990:9990
environment:
DB_ADDR: keycloak-db
DB_PORT: 3306
DB_DATABASE: keycloak
DB_USER: keycloak
DB_PASSWORD: keycloak
DB_JDBC_PARAMS: useSSL=false&allowPublicKeyRetrieval=true

KEYCLOAK_IMPORT: /opt/jboss/keycloak_install_stage/realms/ct-realm-dev.json
KEYCLOAK_USER: keycloak.admin
KEYCLOAK_PASSWORD: keycloak.admin

KC_HOSTNAME_STRICT: false

DEBUG_PORT: 8888
PROXY_ADDRESS_FORWARDING: ‘true’

Make sure that the DB_XXX parameter values in the ct-keycloak-iam container match that of MySQL.

4. Configure the MySQL Driver and Module

This is already done by the build-keycloak.sh, a script which copies the MySQL driver and module.xml file to the extracted Keycloak server inside the Docker container.

Here’s our MySQL module file.

<?xml version=”1.0" encoding=”UTF-8"?>
<module
xmlns=”urn:jboss:module:1.0" name=”com.mysql.jdbc”>
<resources>
<resource-root path=”mysql-connector-java-8.0.29.jar”/>
</resources>
<dependencies>
<module name=”javax.api”/>
<module name=”javax.transaction.api”/>
</dependencies>
</module>

5. Add the MySQL Datasource and Driver Configuration in Keycloak

This is handled by the set-database.cli script which installs the data source and driver configuration by using the values from the environment variables such as database url, username, password, and JDBC params.

/subsystem=datasources/data-source=KeycloakDS: remove()
/subsystem=datasources/data-source=KeycloakDS: add(jndi-name=java:jboss/datasources/KeycloakDS,enabled=true,use-java-context=true,use-ccm=true, connection-url=jdbc:mysql://${env.DB_ADDR:mysql}:${env.DB_PORT:3306}/${env.DB_DATABASE:keycloak}${env.DB_JDBC_PARAMS:}, driver-name=mysql)
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=user-name, value=${env.DB_USER:keycloak})
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=password, value=${env.DB_PASSWORD:password})
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=check-valid-connection-sql, value=”SELECT 1")
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=background-validation, value=true)
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=background-validation-millis, value=60000)
/subsystem=datasources/data-source=KeycloakDS: write-attribute(name=flush-strategy, value=IdleConnections)
/subsystem=datasources/jdbc-driver=mysql:add(driver-name=mysql, driver-module-name=com.mysql.jdbc,driver-xa-datasource-class-name=com.mysql.cj.jdbc.MysqlXADataSource)

6. Running the Project

If you’re familiar with docker-compose then you know that it’s our entry point to our custom Keycloak server.

Before running it, make sure to comment on the line that imports the SPIs, or become my sponsor in GitHub, so that you can gain access to those restricted projects.

docker-compose -f ./keycloak-docker-assembly/docker/docker-compose-dev.yml up — build

--

--

czetsuya

Open for Collaboration | Senior Java Backend Developer