Docker "start" fails with JDBC driver error, "start-dev" appears to work fine

Running Keycloak 18.0.2 build from quay.io, a few integrations added.

If I start the docker image with “start” (sudo docker run -d -e DB_VENDOR=postgres -e KC_DB_URL=jdbc:postgresql://{aws_rds_postgres_instance}:5432/{db_name} -e DB_PORT=5432 -e DB_DATABASE={db_name} -e DB_USER={db_user) -e DB_PASSWORD={password} -p 8080:8080 --name keycloak_container kc_test_build_js:0.0.14 start), the container fails almost immediately, and I get the following log output:

2023-05-03 23:03:44,304 WARN [io.quarkus.runtime.configuration.ConfigRecorder] (main) Build time property cannot be changed at runtime:

  • quarkus.datasource.jdbc.driver is set to ‘org.h2.jdbcx.JdbcDataSource’ but it is build time fixed to ‘org.postgresql.xa.PGXADataSource’. Did you change the property quarkus.datasource.jdbc.driver after building the application?
  • quarkus.datasource.health.enabled is set to ‘false’ but it is build time fixed to ‘true’. Did you change the property quarkus.datasource.health.enabled after building the application?
    2023-05-03 23:03:45,272 INFO [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: FrontEnd: , Strict HTTPS: true, Path: , Strict BackChannel: false, Admin: , Port: -1, Proxied: false
    2023-05-03 23:03:45,512 WARN [io.agroal.pool] (agroal-11) Datasource ‘’: No suitable driver found for jdbc:postgresql://{aws_rds_postgres_instance}:5432/{db_name}
    2023-05-03 23:03:45,519 WARN [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator] (JPA Startup Thread: keycloak-default) HHH000342: Could not obtain connection to query metadata: java.sql.SQLException: No suitable driver found for jdbc:postgresql://{aws_rds_postgres_instance}:5432/{db_name}
    at org.h2.jdbcx.JdbcDataSource.getJdbcConnection(JdbcDataSource.java:191)
    at org.h2.jdbcx.JdbcDataSource.getXAConnection(JdbcDataSource.java:352)
    at io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:216)
    at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:513)
    at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:494)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at io.agroal.pool.util.PriorityScheduledExecutor.beforeExecute(PriorityScheduledExecutor.java:75)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1126)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:829)

2023-05-03 23:03:47,255 WARN [io.agroal.pool] (agroal-11) Datasource ‘’: No suitable driver found for jdbc:postgresql://{aws_rds_postgres_instance}:5432/{db_name}
2023-05-03 23:03:47,647 WARN [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
2023-05-03 23:03:47,657 WARN [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
2023-05-03 23:03:47,721 INFO [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller ‘org.infinispan.jboss.marshalling.core.JBossUserMarshaller’
2023-05-03 23:03:48,060 INFO [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000128: Infinispan version: Infinispan ‘Triskaidekaphobia’ 13.0.9.Final
2023-05-03 23:03:48,288 INFO [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000078: Starting JGroups channel ISPN
2023-05-03 23:03:48,288 INFO [org.infinispan.CLUSTER] (keycloak-cache-init) ISPN000088: Unable to use any JGroups configuration mechanisms provided in properties {}. Using default JGroups configuration!
2023-05-03 23:03:48,423 WARN [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the send buffer of socket MulticastSocket was set to 1.00MB, but the OS only allocated 212.99KB
2023-05-03 23:03:48,424 WARN [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the receive buffer of socket MulticastSocket was set to 20.00MB, but the OS only allocated 212.99KB
2023-05-03 23:03:48,425 WARN [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the send buffer of socket MulticastSocket was set to 1.00MB, but the OS only allocated 212.99KB
2023-05-03 23:03:48,426 WARN [org.jgroups.protocols.UDP] (keycloak-cache-init) JGRP000015: the receive buffer of socket MulticastSocket was set to 25.00MB, but the OS only allocated 212.99KB

However, if I start the image with “start-dev” (sudo docker run -d -e DB_VENDOR=postgres -e KC_DB_URL=jdbc:postgresql://{aws_rds_postgres_instance}:5432/{db_name} -e DB_PORT=5432 -e DB_DATABASE={db_name} -e DB_USER={db_user) -e DB_PASSWORD={password} -p 8080:8080 --name keycloak_container kc_test_build_js:0.0.14 start-dev), I get an (apparently) functional keycloak deployment.

Nothing else is different; been over environmental variables, etc. I can go into the container and start it manually, but I get the exact same output; I can only start it using “start-dev” rather than “start”. Been around and around with this, but can’t seem to find a cause. It’s likely I’m missing something obvious; can anyone steer me in the right direction? Thanks!

Some coworkers suggested that “start-dev” might be using the built-in database instead of the external postgres box–that it wasn’t actually working at all. This was a good idea, so I logged into the Keycloak frontend from another box, created a test realm with a unique name, then logged into the postgres box and queried it–sure enough, there was my test realm. So, the thing can and does connect to the postgres box, which means the JDBC driver shouldn’t actually be the issue–it just won’t connect when I use “start” instead of “start-dev”.

For 18.0.2, you’ll need to build a custom image to use external database. For newer versions 19+ this is not necessary as the start command will run the configuration.

Check this doc for image customization: Running Keycloak in a container - Keycloak

1 Like

Awesome; thank you for the response!

We’re building the image before deploying, and I think that we’re doing everything correctly. Here’s the Dockerfile:

FROM quay.io/keycloak/keycloak:18.0.2

# Enable health and metrics support
ENV KC_HEALTH_ENABLED=true
# ENV KC_METRICS_ENABLED=true

# Configure a database vendor
ENV KC_DB=postgres

# Enables HTTP listener
ENV KC_HTTP_ENABLED=true
ENV KC_HOSTNAME_STRICT=false

# Add custom extensions
COPY {some integrations}
USER root
RUN touch {some integration}
RUN mkdir -p /opt/jboss/keycloak/modules/system/layers/base/org/postgresql/jdbc/main/
RUN curl -L https://jdbc.postgresql.org/download/postgresql-42.2.23.jar -o /opt/jboss/keycloak/modules/system/layers/base/org/postgresql/jdbc/main/postgresql-42.2.23.jar
COPY module.xml /opt/jboss/keycloak/modules/system/layers/base/org/postgresql/jdbc/main/


# Create /waf directory and set permissions
RUN mkdir -p /waf
RUN chmod 777 /waf

EXPOSE 8080

ENV KC_DB_URL=jdbc:postgresql://{address_of_postgres_db}
ENV KC_DB_USERNAME={username}
ENV KC_DB_PASSWORD={password}

ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

I’ve no reason to think any of this is incorrect, as “start-dev” is apparently able to utilize this information to connect and read/write to the postgres box. Any obvious issues that I’m missing, tho? I’m still fairly certain I’m just making a silly mistake of some sort…

You need a

RUN /opt/keycloak/bin/kc.sh build

after you set the KC_DB=postgres

Also, you don’t need to include the postgres driver, because keycloak already comes with it:

If you have a load balancer in front of this server, just set KC_PROXY=edge

1 Like

OMG, thank you so much–that did, in fact, get rid of the error and allow my container to start. This is just a test deployment for me to get a little info about the build process; looks like I need to do some more work here, but this has gotten me going again–I sincerely appreciate it!

1 Like

I suggest you use Keycloak 21, which is the latest version.

1 Like

That is the end goal, but I still don’t understand the custom integrations well enough to be confident that I can integrate them into the quarkus-based Keycloak versions. Another team did that, and I’m sort of having to work backwards and gain some knowledge that wasn’t well-documented, I’m afraid.

Currently, we have to run a series of Maven commands to add the jar files, copy 'em to target, and build the docker image. I understand that quarkus is supposed to make this easier, but right now, I’m just trying to duplicate work that this other team had done. I was holding off on moving to later versions until I got this working. That said, maybe it’s the wrong approach–do you happen to know if the procedures for integrating custom jar files is significantly different following the switch to quarkus?

Sincere apologies if these are dumb questions–got a lot to learn here!

If you are using version 18, you’re already on quarkus.

From 18 to 21, we had some changes, mainly in package reorganization. If your custom code is related to UserStorageProvider, you’ll need to import the legacy packages, but it’s mainly that. See the release note with info about the changes in the storage framework

1 Like

Oh good lord; I thought the quarkus transition didn’t take place until v19. Let me read up on those changes a bit; if we’re already there, you’re probably right–I should just use v21.

Thank you so much for your help; I can’t begin to tell you how much I appreciate it!

Quick update–we’re using the latest version! Custom authenticator JARs needed a little work, but we’re up and running now. Got some new bizarre problems, but working on 'em. Thank you so much for getting back to me; this was incredibly helpful and ultimately got us in a much better place.