javaspring-bootdockerspring-securitykeycloak

How to keep the realms, users and roles in Keycloak to be persisted when using docker and docker compose to run it


I have an Spring boot java application that uses Keycloak for authentication and authorization. I have created my realm and its users and roles. I want to dockerize the application using docker compose. So I have crated a docker image of my java application. But when I want to create a Keycloak instance(pulling Keyckloak image from dockerhub), I will lose my persisted realms, users and roles which I had created before because it creates a new Keycloak from the pulled docker image. How to keep this data persisted, every time I run the application using docker compose? Actually I need the Keycloak data(realms, users and roles) to be initialized automatically whenever I run docker compose.

Update:

Let me make the problem clearer.

I want to put the codes on Github and when somebody gets and runs it (thorough docker compose); by predefined keycloak users and passwords, use the application. The problem is that, when somebody each time runs the code by docker compose, there is no realm, users and roles because the Keycloak image is pulled and runs without any data(realms, user and so on). Actually I do not want the users who run the application, define the Keycloak data(realm, user and so on). I want this data already be exist on each application running so the users can login to my application and use it.

application.yml:

spring:
  application:
    name: my-client
  security:
    oauth2:
      client:
        registration:
          myclientapp:
            client-id: my-client-app
            client-secret: secrectKey12345
            scope: openid, profile, roles
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:8085/login/oauth2/code/myclientapp
        provider:
          myclientapp:
            authorization-uri: http://localhost:8080/realms/myclientapp/protocol/openid-connect/auth
            token-uri: http://localhost:8080/realms/myclientapp/protocol/openid-connect/token
            jwk-set-uri: http://localhost:8080/realms/myclientapp/protocol/openid-connect/certs
            user-info-uri: http://localhost:8080/realms/myclientapp/protocol/openid-connect/userinfo
            user-name-attribute: preferred_username

pox.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.my-client</groupId>
    <artifactId>client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>client</name>
    <description>Demo project for Spring Client</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Thanks a lot.


Solution

  • Short answer

    Export your Keycloak realm and users and add it to the container /opt/keycloak/data/import/ folder.

    Step by step

    Once your realm clients and users are configured with Keycloak admin UI, in Docker desktop:

    cd /opt/keycloak/bin/
    sh ./kc.sh export --dir /tmp/keycloak/ --users realm_file
    
        volumes:
          - ./keycloak/import/:/opt/keycloak/data/import/
    

    Sample complete projects doing that: