You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keycloak从v16迁移至v21后无法读取Realm及用户,Postgres连接失败

Keycloak v21 迁移连接PostgreSQL并读取原有数据问题

我们已将Keycloak v16容器化,现计划迁移至v21版本。使用Postgres数据库,其中已创建好Realm和用户,但升级至v21后,Keycloak显示Realm和用户为空,数据库数据仍存在。尝试配置连接Postgres容器后出现连接拒绝错误,错误信息显示尝试连接localhost:5432被拒绝。


相关配置

新Dockerfile

FROM quay.io/keycloak/keycloak:21.0.2

COPY themes/ /opt/jboss/keycloak/themes/
ADD ./standalone-ha.xml /opt/jboss/keycloak/standalone/configuration/standalone-ha.xm

standalone-ha.xml配置片段

<spi name="connectionsJpa">
                <provider name="default" enabled="true">
                    <properties>
                        <property name="dataSource" value="java:jboss/datasources/KeycloakDS"/>
                        <property name="initializeEmpty" value="true"/>
                        <property name="migrationStrategy" value="update"/>
                        <property name="migrationExport" value="${jboss.home.dir}/keycloak-database-update.sql"/>
                        <property name="schema" value="${env.DB_SCHEMA:public}"/>
                    </properties>
                </provider>
            </spi>

修改后的docker-compose配置

db:
    image: postgres:13.2
    ports:
    - "5432:5432"
    environment:
      POSTGRES_PASSWORD: 'xxx'
    # volumes:
    # - /Volumes/DATA/docker_volume/pgdata:/var/lib/postgresql/data

  keycloak:
    depends_on:
      - db
    image: mykeycloak
    environment:
      KC_DB: postgres
      KC_DB_ADDR: db
      KC_DB_DATABASE: keycloak
      KC_DB_USER: postgres
      KC_DB_SCHEMA: public
      KC_DB_PASSWORD: xxx
      KEYCLOAK_ADMIN: keycloak_admin
      KEYCLOAK_ADMIN_PASSWORD: xxx
      KEYCLOAK_FRONTEND_URL: http://localhost:8080/auth/
    volumes:
      - ./common/keycloak/disable-theme-cache.cli:/opt/jboss/startup-scripts/disable-theme-cache.cli
    command: start-dev --http-relative-path /auth
    ports:
      - 8080:8080

错误信息

2023-06-22 10:18:30 2023-06-22 08:18:30,593 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.
2023-06-22 10:18:30     at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:319)
2023-06-22 10:18:30     at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
2023-06-22 10:18:30     at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:247)
2023-06-22 10:18:30     at org.postgresql.Driver.makeConnection(Driver.java:434)
2023-06-22 10:18:30     at org.postgresql.Driver.connect(Driver.java:291)
2023-06-22 10:18:30     at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:681)
2023-06-22 10:18:30     at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:229)
2023-06-22 10:18:30     at org.postgresql.ds.common.BaseDataSource.getConnection(BaseDataSource.java:103)
2023-06-22 10:18:30     at org.postgresql.xa.PGXADataSource.getXAConnection(PGXADataSource.java:49)
2023-06-22 10:18:30     at org.postgresql.xa.PGXADataSource.getXAConnection(PGXADataSource.java:35)
2023-06-22 10:18:30     at io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:232)
2023-06-22 10:18:30     at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:536)
2023-06-22 10:18:30     at io.agroal.pool.ConnectionPool$CreateConnectionTask.call(ConnectionPool.java:517)
2023-06-22 10:18:30     at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
2023-06-22 10:18:30     at io.agroal.pool.util.PriorityScheduledExecutor.beforeExecute(PriorityScheduledExecutor.java:75)
2023-06-22 10:18:30     at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
2023-06-22 10:18:30     at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
2023-06-22 10:18:30     at java.base/java.lang.Thread.run(Thread.java:833)
2023-06-22 10:18:30 Caused by: java.net.ConnectException: Connection refused
2023-06-22 10:18:30     at java.base/sun.nio.ch.Net.pollConnect(Native Method)
2023-06-22 10:18:30     at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672)
2023-06-22 10:18:30     at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542)
2023-06-22 10:18:30     at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597)
2023-06-22 10:18:30     at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
2023-06-22 10:18:30     at java.base/java.net.Socket.connect(Socket.java:633)
2023-06-22 10:18:30     at org.postgresql.core.PGStream.createSocket(PGStream.java:241)
2023-06-22 10:18:30     at org.postgresql.core.PGStream.<init>(PGStream.java:98)
2023-06-22 10:18:30     at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:109)
2023-06-22 10:18:30     at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:235)
2023-06-22 10:18:30     ... 17 more
2023-06-22 10:18:30 

解决方案

1. 移除自定义standalone-ha.xml配置

Keycloak v17+ 基于Quarkus重构,不再使用Wildfly时代的standalone-ha.xml配置文件。当前Dockerfile中添加该文件会覆盖默认配置,导致环境变量中的数据库连接参数失效,Keycloak仍尝试连接默认的localhost数据库。

修改Dockerfile,删除添加standalone-ha.xml的行:

FROM quay.io/keycloak/keycloak:21.0.2

COPY themes/ /opt/jboss/keycloak/themes/

2. 确保Postgres服务就绪

depends_on仅保证容器启动顺序,不确保Postgres服务完全可用。可通过以下方式解决:

方式一:给Postgres容器添加健康检查

db:
  image: postgres:13.2
  ports:
  - "5432:5432"
  environment:
    POSTGRES_PASSWORD: 'xxx'
    POSTGRES_DB: keycloak  # 提前创建目标数据库,避免Keycloak启动时创建失败
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U postgres -d keycloak"]
    interval: 5s
    timeout: 5s
    retries: 5
  # volumes:
  # - /Volumes/DATA/docker_volume/pgdata:/var/lib/postgresql/data

方式二:添加等待脚本

创建wait-for-postgres.sh脚本:

#!/bin/bash
set -e

host="$1"
shift
cmd="$@"

until pg_isready -h "$host" -U "postgres"; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

>&2 echo "Postgres is up - executing command"
exec $cmd

在docker-compose中挂载并使用:

keycloak:
  depends_on:
    - db
  image: mykeycloak
  environment:
    KC_DB: postgres
    KC_DB_ADDR: db
    KC_DB_DATABASE: keycloak
    KC_DB_USER: postgres
    KC_DB_SCHEMA: public
    KC_DB_PASSWORD: xxx
    KEYCLOAK_ADMIN: keycloak_admin
    KEYCLOAK_ADMIN_PASSWORD: xxx
    KEYCLOAK_FRONTEND_URL: http://localhost:8080/auth/
  volumes:
    - ./common/keycloak/disable-theme-cache.cli:/opt/jboss/startup-scripts/disable-theme-cache.cli
    - ./wait-for-postgres.sh:/opt/jboss/keycloak/wait-for-postgres.sh
  command: ["/opt/jboss/keycloak/wait-for-postgres.sh", "db", "start-dev", "--http-relative-path", "/auth"]
  ports:
    - 8080:8080

3. 添加数据库迁移参数

Keycloak v21需明确指定迁移策略,确保自动升级v16的数据库结构:
在Keycloak的command中添加--spi-connections-jpa-migration-strategy=update参数:

command: start-dev --http-relative-path /auth --spi-connections-jpa-migration-strategy=update

4. 验证数据库连接参数

确认所有KC_DB开头的环境变量配置正确:

  • KC_DB=postgres:指定数据库类型为PostgreSQL
  • KC_DB_ADDR=db:对应Docker Compose中的Postgres服务名
  • KC_DB_DATABASE=keycloak:目标数据库名,需确保Postgres中已存在
  • KC_DB_USER=postgres:数据库用户名
  • KC_DB_PASSWORD=xxx:数据库密码
  • KC_DB_SCHEMA=public:数据库schema

5. 启动验证

执行docker-compose down -v清理旧容器和卷,再执行docker-compose up --build启动服务。查看Keycloak日志,确认数据库连接成功且迁移脚本执行完成,即可看到原有Realm和用户数据。


内容的提问来源于stack exchange,提问作者Marko Zadravec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 06:17:06