Hi,
I created Dockerfile based on Keycloak documentation:
FROM quay.io/keycloak/keycloak:20.0.2 as builder
ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true
ENV KC_DB=postgres
ENV KC_DB_URL=jdbc:postgres://auth-keycloak-db:15434/keycloak
ENV KC_DB_USERNAME=keycloak
ENV KC_DB_PASSWORD=keycloak
WORKDIR /opt/keycloak
COPY <provider>.jar providers/
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
RUN bin/kc.sh build
#
FROM quay.io/keycloak/keycloak:20.0.2
COPY --from=builder /opt/keycloak/ /opt/keycloak/
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
Created this docker-compose file, regarding usage of postgres-db:
version: "3.8"
services:
auth-keycloak:
build:
context: ..
dockerfile: deploy/Dockerfile
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin
- KC_HOSTNAME=auth-keycloak
ports:
- "9990:8443"
depends_on:
- "auth-keycloak-db"
command: ["start"]
auth-keycloak-db:
image: postgres:13.3
volumes:
- ./data/keycloak/db:/var/lib/postgresql/data
ports:
- "15434:5432"
environment:
- POSTGRES_DB=keycloak
- POSTGRES_USER=keycloak
- POSTGRES_PASSWORD=keycloak
It works this way. The problem is, regarding database configuration, it only works THIS way (and only for 20.0.2, in 20.0.3 I had no success at all), i.e. by setting env in build stage.
I need to specify db connection info in docker-compose as environment variables, for example, but then Keycloak doesn’t recognize any KC env config. Besides docker-compose envs, tried also: as start argument (cli), with --optimized
option (as mentioned in v19 doc), setting in Dockerfile after build stage and so on, also I’ve read many other discussions, but none of these seems to work for me.
I’ll give some error examples, like when I set as docker-compose env variables, including:
- KC_DB_URL=jdbc:postgres://auth-keycloak-db:15434/keycloak
- KC_DB_USERNAME=keycloak
- KC_DB_PASSWORD=keycloak
Gives error below (as expecting h2 db):
2023-02-03 16:24:30,883 WARN [io.agroal.pool] (agroal-11) Datasource '<default>': URL format error; must be "jdbc:h2:{ {.|mem:}[name] | [file:]fileName | {tcp|ssl}:[//]server[:port][,server2[:port]]/name }[;key=value...]" but is "jdbc:postgres://auth-keycloak-db:15434/keycloak" [90046-214]
2023-02-03 16:24:30,885 WARN [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator] (JPA Startup Thread: keycloak-default) HHH000342: Could not obtain connection to query metadata: org.h2.jdbc.JdbcSQLNonTransientConnectionException: URL format error; must be "jdbc:h2:{ {.|mem:}[name] | [file:]fileName | {tcp|ssl}:[//]server[:port][,server2[:port]]/name }[;key=value...]" but is "jdbc:postgres://auth-keycloak-db:15434/keycloak" [90046-214]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:678)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:477)
at org.h2.message.DbException.get(DbException.java:223)
at org.h2.engine.ConnectionInfo.getFormatException(ConnectionInfo.java:687)
at org.h2.engine.ConnectionInfo.<init>(ConnectionInfo.java:86)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:113)
at org.h2.jdbcx.JdbcDataSource.getXAConnection(JdbcDataSource.java:322)
at io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:232)
at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:535)
at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:516)
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)
auth-keycloak |
If I add - KC_DB=postgres
to it (regarding explicitly not h2 db), it gives have another error, like pointing to a default db:
2023-02-03 16:47:59,873 WARN [io.agroal.pool] (main) Datasource '<default>': Ignoring property 'URL': null
2023-02-03 16:47:59,874 WARN [io.agroal.pool] (main) Datasource '<default>': Ignoring property 'URL': null
2023-02-03 16:48:00,156 WARN [io.agroal.pool] (agroal-11) Datasource '<default>': Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
2023-02-03 16:48:00,160 WARN [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator] (JPA Startup Thread: keycloak-default) HHH000342: Could not obtain connection to query metadata: org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:319)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:247)
at org.postgresql.Driver.makeConnection(Driver.java:434)
at org.postgresql.Driver.connect(Driver.java:291)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)
at org.postgresql.ds.common.BaseDataSource.getConnection(BaseDataSource.java:103)
at org.postgresql.xa.PGXADataSource.getXAConnection(PGXADataSource.java:49)
at org.postgresql.xa.PGXADataSource.getXAConnection(PGXADataSource.java:35)
at io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:232)
at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:535)
at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:516)
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)
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412)
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255)
at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.base/java.net.Socket.connect(Socket.java:609)
at org.postgresql.core.PGStream.createSocket(PGStream.java:241)
at org.postgresql.core.PGStream.<init>(PGStream.java:98)
at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:109)
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:235)
... 17 more
If I replace start
command to show-config
in compose, I can see all env set properly:
Current Configuration:
kc.cache = ispn (PersistedConfigSource)
kc.config.built = true (SysPropConfigSource)
kc.db = postgres (KcEnvVarConfigSource)
kc.db-password = ******* (KcEnvVarConfigSource)
kc.db-url = jdbc:postgres://auth-keycloak-db:15434/keycloak (KcEnvVarConfigSource)
kc.db-username = keycloak (KcEnvVarConfigSource)
kc.db.password = keycloak (KcEnvVarConfigSource)
kc.db.url = jdbc:postgres://auth-keycloak-db:15434/keycloak (KcEnvVarConfigSource)
kc.db.username = keycloak (KcEnvVarConfigSource)
kc.health-enabled = true (PersistedConfigSource)
kc.hostname = auth-keycloak (KcEnvVarConfigSource)
...
But when I start keycloak, it doesn’t see any of those. In addition to that, if I keep these env in build stage and then try to set again (any other further stage in Dockerfile or docker-compose), it seems to override the same env variables, but then Keycloak just ignore all of them. I mean: any other combination than keeping these KC_DB
env ONLY in Dockerfile build stage does not work, at least on my experience, and it’s not making much sense to me, so if anyone went thru that or maybe helping understanding, I would really appreciate.