How to run Keycloak with Docker

Keycloak is an Open Source Identity and Access Management solution for modern Applications and Services. Docker Images for Keycloak are available on the Docker repository. In this tutorial we will learn how to run it with Docker, using some common environment parameters.

Available Keycloak distributions

The Keycloak Docker Image for is available in this repository: . You can use it in two different flavours:

  • Keycloak built on Quarkus: This is Keycloak which uses Quarkus as Runtime environment. The latest version of Keycloak with Quarkus ( May 2023 ) is 21.1.1
  • Keycloak legacy: This is the legacy distribution of Keycloak which uses WildFly as Runtime engine.

That being said, let’s see how to start Keycloak on Docker in both distributions.

Keycloak with Docker powered by Quarkus

Firstly, it is worth mentioning that you can use either the docker command or podman to achieve the same results. We will use docker in this section.

To pull the latest Docker Image of Keycloak you can run from the Command Line:

$ docker pull

On the other hand, you can pull and start Keycloak with a single command. Here is how to start it in development mode:

docker run --name keycloak_dev -p 8080:8080 \
        -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \ \

if you want to start Keycloak on a different server port:

docker run --name keycloak_dev -p 8180:8180 \
        -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \ \
        start-dev --http-port=8180

Then, to start Keycloak in production mode with PostgreSQL as database, use the following example command:

docker run --name keycloak_auto_build -p 8080:8080 \
        -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \ \
        start \
        --auto-build \
        --db=postgres --features=token-exchange \
        --db-url=jdbc:postgresql://localhost:5432/keycloak --db-username=postgres --db-password=postgres \
        --https-key-store-file=server.keystore --https-key-store-password=secret

Update the Database and Keystore settings accordingly.

Finally, let’s see how to import an existing Realm when using Keycloak Docker Image. To do that, you have to use the –import-realm option at startup. For example, with docker-compose the following file will import the Realm available in the local file /home/keycloak/realm.json:

      - "8080:8080"
      KEYCLOAK_ADMIN: admin 
      - start-dev 
      - --import-realm
      - /home/keycloak/realm.json:/opt/keycloak/data/import/realm.json

To start Keycloak, simply run:

docker-compose up

Finally, verify that the Realm in realm.json has been imported at start up:

keycloak with docker example

Using Keycloak legacy distribution

To run the legacy distribution, which uses WildFly as runtime engine, you need to refer to the Image. Please notice the legacy tag that indicates to use the WildFly distribution. Here is how to start it, adding an Admin user:

docker run --rm --name keycloak -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin  -p 8080:8080  -it

To use a different port, such as port 8180, you can use the following command:

docker run --rm --name keycloak -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin  -p 8180:8180  -it  -b  -Djboss.http.port=8180

You will see that Keycloak starts in foreground and binds to port 8180 (by default port 8080 will be used but it can clash with other services, like WildFly, running on that port):

09:16:07,923 INFO  [] (Controller Boot Thread) WFLYSRV0025: Keycloak 15.0.2 (WildFly Core 15.0.1.Final) started in 22594ms - Started 692 of 977 services (686 services are lazy, passive or on-demand)
09:16:07,925 INFO  [] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on
09:16:07,925 INFO  [] (Controller Boot Thread) WFLYSRV0051: Admin console listening on

Next, login to the Admin Console, which is available at: http://localhost:8180 with admin/admin:

keycloakd docker

Adding other Keycloak users

The legacy image of Keycloak ships with the script add-user-keycloak script available in the /opt/jboss/keycloak/bin folder. You can use it to add some extra users.

Firstly, collect the container id:

$ docker ps

CONTAINER ID        IMAGE                        

Next, run the following command:

docker exec 31a5c280ecdf /opt/jboss/keycloak/bin/ -u frank -p foo

Then, you will see the following log:

Added 'frank' to '/opt/jboss/keycloak/standalone/configuration/keycloak-add-user.json', restart server to load user

Finally, restart the container with:

docker restart 31a5c280ecdf

Changing Keycloak Log Level

You can set Keycloak log level through the following environment variables:

  • KEYCLOAK_LOGLEVEL: Specifies the log level for Keycloak (default is INFO)
  • ROOT_LOGLEVEL: Specifies the log level for underlying container (default is INFO)

Example usage:

docker run --rm --name keycloak -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin -p 8180:8180 -it -b -e KEYCLOAK_LOGLEVEL=TRACE

Managing Keycloak Realms running on Docker

You can approach Keycloak management on docker in at least two ways. One option is using the Web Console as we have seen in the previous section. Another option is to use the Keycloak CLI which you can trigger with a docker exec command.

Let’s see it in action. Firstly, we need to login to Keycloak server:

docker exec 31a5c280ecdf /opt/jboss/keycloak/bin/ config credentials --server http://localhost:8180/auth --realm master --user admin --password admin

We have now logged with the admin user. Let’s use this session to add another realm:

docker exec 31a5c280ecdf /opt/jboss/keycloak/bin/ create realms -s realm=wildfly-realm -s enabled=true -o

If you want a quickstart example of Keycloak CLI you can check this tutorial: Keycloak quickstart example using CLI

Importing a Keycloak legacy Realm at start up

Just in case you want to boot Keycloak and have your Realm imported, you can add the KEYCLOAK_IMPORT Environment variable and the Volume argument (-v) to specify the path where the JSON Realm file will be picked up:

docker run --rm \ 
--name keycloak \ 
-e KEYCLOAK_USER=admin \ 
-e KEYCLOAK_IMPORT=/tmp/realm.json -v /tmp/realm.json:/tmp/realm.json \ 
-p 8180:8180 \ 
-it \ 
-b \ 
-Djboss.http.port=8180 \ 

Exporting a Keycloak legacy Realm

If you want to export a realm that you have created you’ll need to ensure the container running Keycloak has a volume mapped. For example you can start Keycloak setting the volume (‘v’) option to the /tmp folder:

docker run -d -p 8180:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin -v $(pwd):/tmp --name keycloak

Then, you can then get the export from this instance by running:

docker exec -it keycloak keycloak/bin/ \ 
-Djboss.socket.binding.port-offset=100 -Dkeycloak.migration.action=export \ 
-Dkeycloak.migration.provider=singleFile \ 
-Dkeycloak.migration.realmName=my_realm \ 
-Dkeycloak.migration.usersExportStrategy=REALM_FILE \ 

(notice we use -Djboss.socket.binding.port-offset=100 so that the export runs on a different port than Keycloak itself).

Configuring a Database for Keycloak Image

Keycloak image supports multiple database as backend. You can specify the DB vendor directly with the DB_VENDOR environment variable. Supported values are:

  • h2 for the embedded H2 database,
  • postgres for the Postgres database,
  • mysql for the MySql database.
  • mariadb for the MariaDB database.
  • oracle for the Oracle database.
  • mssql for the Microsoft SQL Server database.

Environment variable names can be used to configure any of the above Database type:

  • DB_ADDR: This is the hostname of the database (optional).
  • DB_PORT: This is the port of the database (optional, default is DB vendor default port)
  • DB_DATABASE: Specify name of the database to use (optional, default is keycloak).
  • DB_SCHEMA: Specify name of the schema to use for DB that support schemas.
  • DB_USER: This is the user to authenticate against the database (optional, default is “).
  • DB_USER_FILE: This is the user to authenticate to the database via file input (alternative to DB_USER).
  • DB_PASSWORD: Specify user’s password to use to authenticate to the database (optional, default is “).
  • DB_PASSWORD_FILE: Specify user’s password to use to authenticate to the database via file input (alternative to DB_PASSWORD).

PostgreSQL example

Firstly, start a PostgreSQL instance:

docker run -d --name postgres --net keycloak-network -e POSTGRES_DB=keycloak -e POSTGRES_USER=keycloak -e POSTGRES_PASSWORD=password postgres

Next, launch the Keycloak server:

docker run --name keycloak --net keycloak-network  -e DB_USER=keycloak -e DB_PASSWORD=password

How to use docker-compose to start Keycloak

Finally, when using Keycloak with an external Database, it is common to use the docker-compose tool to configure all services in a single file. For example, this is a Docker compose example to bind Keycloak with PostgreSQL database:

version: '3'

      driver: local

      image: postgres
        - postgres_data:/var/lib/postgresql/data
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: password
        DB_ADDR: postgres
        DB_DATABASE: keycloak
        DB_USER: keycloak
        DB_SCHEMA: public
        DB_PASSWORD: password
        KEYCLOAK_USER: admin
        KEYCLOAK_PASSWORD: Pa55w0rd
        # Uncomment the line below if you want to specify JDBC parameters. The parameter below is just an example, and it shouldn't be used in production without knowledge. It is highly recommended that you read the PostgreSQL JDBC driver documentation in order to use it.
        #JDBC_PARAMS: "ssl=true"
        - 8080:8080
        - postgres

To run it, execute:

 docker-compose up

More example of Keycloak and Docker compose are available here: