Keycloak Docker Compose 部署指南
Docker Compose 部署 Keycloak 26.8.1:dev 与 Postgres+生产启动两套编排、初始化管理员、数据持久化与升级兼容实录。
Keycloak Docker Compose 部署指南
> 目标:用 Docker Compose 在 Ubuntu 22.04 上完成 Keycloak 26.8.1 的两种落地形态——开发验证用的 dev 模式(H2 内置存储)与生产可用的 Postgres 16 + 生产启动模式,覆盖镜像准备、编排文件、初始化管理员、数据持久化验证与升级兼容,全部配置与回显逐行实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04(x86_64)
- Docker Engine:27.5.1(含 Compose v2 编排器,实测
docker compose version为Docker Compose version v5.5.1) - Keycloak 镜像:
quay.io/keycloak/keycloak,实测固定版本 26.8.1(Quarkus 3.40.1 底座) - 数据库镜像:
postgres:16 - 端口约定:宿主机 8080 → Keycloak 8080;Postgres 不向宿主机映射端口(仅编排内网访问)
- 数据落盘目录:
/opt/data/keycloak-pg(绑定挂载到 Postgres 数据目录) - 容器命名:dev 形态
keycloak-26.8.1-sso;生产形态keycloak-16-db+keycloak-26.8.1-pg
💡 说明:本机 8080 端口在 IPv4 侧被宿主机既有服务(haproxy)占用,因此端口映射写作
[::]:8080:8080(仅经 IPv6 栈发布);若无此冲突,直接写8080:8080即可。
二、镜像与版本准备
拉取官方镜像并确认实际版本——生产编排建议固定具体版本号 tag,避免 latest 随上游漂移:
docker pull quay.io/keycloak/keycloak:latest
docker pull postgres:16
实测回显(节选):
latest: Pulling from keycloak/keycloak
Digest: sha256:56e5a5d2f1bbd7f22c66b5b451e034ce7754a2bfe8b6d05f14b7d2a36ae4d472
Status: Downloaded newer image for quay.io/keycloak/keycloak:latest
用容器内自带的 kc.sh --version 核对镜像内真实版本:
docker run --rm quay.io/keycloak/keycloak:latest --version
实测回显:
Keycloak 26.8.1
JVM: 21.0.12.1 (Red Hat, Inc. OpenJDK 64-Bit Server VM 21.0.12.1+1-LTS)
OS: Linux 6.8.0-138-generic amd64
确认 latest 当前解析为 26.8.1 后,后续编排统一写 quay.io/keycloak/keycloak:26.8.1(tag 与 digest 一一对应,升级时只改 tag)。
三、方案一:dev 模式部署(start-dev,开箱即用)
3.1 编排文件
dev 模式(start-dev)跳过 hostname/TLS 硬校验、使用内置 H2 存储,适合功能验证与本地联调。compose-dev.yml:
services:
keycloak:
image: quay.io/keycloak/keycloak:26.8.1
container_name: keycloak-26.8.1-sso
command: start-dev
environment:
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: q1w2e3r4
ports:
- "[::]:8080:8080"
适用场景:本地功能验证、与业务应用联调 SSO 流程、临时演示。磁盘占用小(无需独立数据库)、启动快,但数据不跨容器重建持久,禁止用于生产。
3.2 启动与验证
docker compose -f compose-dev.yml -p keycloak-dev up -d
实测回显:
[+] Running 2/2
✔ Network keycloak-dev_default Created
✔ Container keycloak-26.8.1-sso Started
等待约 30 秒后查看状态与服务日志:
docker compose -f compose-dev.yml -p keycloak-dev ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
keycloak-26.8.1-sso quay.io/keycloak/keycloak:26.8.1 "/opt/keycloak/bin/kc…" keycloak 31 seconds ago Up 29 seconds [::]:8080->8080/tcp
docker logs keycloak-26.8.1-sso 2>&1 | grep -E 'started in|Listening on|Keycloak 26' | tail -2
实测回显:
Keycloak 26.8.1 on JVM (powered by Quarkus 3.40.1) started in 9.394s. Listening on: http://0.0.0.0:8080
验证服务可达:
curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://localhost:8080/
实测回显:
HTTP 302
3.3 初始化管理员并登录控制台
编排里已通过 KC_BOOTSTRAP_ADMIN_USERNAME/PASSWORD 声明引导管理员(admin / q1w2e3r4),首次访问 http://localhost:8080/admin/ 即以该账号登录 Admin Console。控制台可达性与登录链路验证:
curl -s -o /dev/null -w 'console HTTP %{http_code}\n' http://localhost:8080/admin/master/console/
实测回显:
console HTTP 200
curl -s -X POST http://localhost:8080/realms/master/protocol/openid-connect/token \
-d 'grant_type=password&client_id=admin-cli&username=admin&password=q1w2e3r4'
实测回显(输出节选,能取得 token 即账号可用):
{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJES29MN3ZFdVJMSnJKNDlTXy1wTUJGd1ZyLVdrczljdU52Rl9HNVhCU1Q4In0...(400 chars)","expires_in":1800,"refresh_expires_in":3600,"token_type":"Bearer","not-before-policy":0,"scope":"profile email"}
⚠️ 注意:dev 模式首次启动若漏配
KC_BOOTSTRAP_ADMIN_*,日志中不会创建任何管理员,首次登录前需补配变量重建或进入容器执行/opt/keycloak/bin/kc.sh bootstrap-admin user。
四、方案二:Postgres + 生产启动模式(start,可落地生产)
4.1 编排文件
compose-prod.yml,要点:Postgres 16 独立服务(不映射宿主端口)、数据绑定挂载到 /opt/data/keycloak-pg、健康检查先行、Keycloak 以 start 生产模式连接数据库:
services:
postgres:
image: postgres:16
container_name: keycloak-16-db
environment:
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: q1w2e3r4
POSTGRES_DB: keycloak
volumes:
- /opt/data/keycloak-pg:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U keycloak -d keycloak"]
interval: 5s
timeout: 3s
retries: 12
keycloak:
image: quay.io/keycloak/keycloak:26.8.1
container_name: keycloak-26.8.1-pg
command: start
depends_on:
postgres:
condition: service_healthy
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: q1w2e3r4
KC_HTTP_ENABLED: "true"
KC_HOSTNAME: localhost
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: q1w2e3r4
ports:
- "[::]:8080:8080"
💡 说明:
KC_DB_URL显式写全 JDBC 地址,避免依赖默认拼接规则;KC_HTTP_ENABLED=true与KC_HOSTNAME=localhost的组合对应"TLS 由前置代理终结、按 Hostname v2 显式声明主机名"的部署形态,参数语义见《Keycloak 配置参数详解》。
4.2 启动与验证
docker compose -f compose-prod.yml -p keycloak-prod up -d
实测回显(健康检查通过后 Keycloak 才启动):
[+] Running 2/2
✔ Container keycloak-16-db Healthy
✔ Container keycloak-26.8.1-pg Started
docker compose -f compose-prod.yml -p keycloak-prod ps
docker logs keycloak-26.8.1-pg 2>&1 | grep -E 'started in|Listening on' | tail -1
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
keycloak-16-db postgres:16 "docker-entrypoint.s…" postgres 2 minutes ago Up 2 minutes 5432/tcp
keycloak-26.8.1-pg quay.io/keycloak/keycloak:26.8.1 "/opt/keycloak/bin/kc…" keycloak 2 minutes ago Up 2 minutes [::]:8080->8080/tcp
Keycloak 26.8.1 on JVM (powered by Quarkus 3.40.1) started in 15.919s. Listening on: http://0.0.0.0:8080
⚠️ 注意:生产模式启动有硬校验,缺 hostname 会直接报
hostname is not configured、缺 HTTPS/HTTP 声明会报Key material not provided to setup HTTPS,逐层补齐的方法见《Keycloak 配置参数详解》6.2 节的三步实录。
4.3 数据持久化验证
数据库数据落在 /opt/data/keycloak-pg(绑定挂载),容器销毁重建不丢数据。实测闭环:先在生产实例创建业务域 quzuo-demo,然后 down 全部销毁、up -d 重建,再查域列表:
docker compose -f compose-prod.yml -p keycloak-prod down
实测回显:
[+] Running 3/3
✔ Container keycloak-26.8.1-pg Removed
✔ Container keycloak-16-db Removed
✔ Network keycloak-prod_default Removed
docker compose -f compose-prod.yml -p keycloak-prod up -d
sleep 45
AT=$(curl -s -X POST http://localhost:8080/realms/master/protocol/openid-connect/token \
-d 'grant_type=password&client_id=admin-cli&username=admin&password=q1w2e3r4' \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["access_token"])')
curl -s http://localhost:8080/admin/realms -H "Authorization: Bearer $AT" \
| python3 -c 'import sys,json;[print("realm:", r["realm"]) for r in json.load(sys.stdin)]'
实测回显:
realm: master
realm: quzuo-demo
验证结论:销毁重建后 quzuo-demo 与管理员账号均完好,持久化链路(绑定挂载 → Postgres → Keycloak 元数据)成立。
五、初始化管理员
两种形态的管理员初始化统一约定:
| 方式 | 触发时机 | 命令/配置 |
|---|---|---|
| 编排变量引导 | 首次启动自动建号 | KC_BOOTSTRAP_ADMIN_USERNAME / KC_BOOTSTRAP_ADMIN_PASSWORD |
| 交互式补建 | 库中已有 master 域、变量不再生效时 | docker compose exec keycloak /opt/keycloak/bin/kc.sh bootstrap-admin user |
实测要点:引导管理员仅在 master 域创建瞬间生效(镜像内 kc.sh --help 对该参数的说明原文:Used only when the master realm is created);为生产环境建议用强密码替换本指南的示例值,并在首次登录后按需开启二步验证。
六、升级与数据兼容
6.1 升级路径(小版本升级)
- 备份先行:导出域数据 + 数据库快照。
docker compose -f compose-prod.yml -p keycloak-prod exec keycloak \
/opt/keycloak/bin/kc.sh export --dir /tmp/kc-export
实测回显(节选):
INFO [org.keycloak.exportimport.dir.DirExportProvider] (main) Realm 'quzuo-demo' - data exported
INFO [org.keycloak.exportimport.dir.DirExportProvider] (main) Realm 'master' - data exported
INFO [org.keycloak.services] (main) KC-SERVICES0035: Export finished successfully
- 改 tag 升级:把编排里的镜像 tag 从
26.8.1改为目标版本(如26.x.y),执行docker compose -f compose-prod.yml -p keycloak-prod pull && docker compose -f compose-prod.yml -p keycloak-prod up -d;新版本容器启动时自动完成数据库 schema 迁移,旧数据无需手工处理。 - 回滚预案:若新版本启动失败,把 tag 改回
26.8.1重新up -d;已执行 schema 迁移的库建议回滚到第 1 步的数据库快照再回退。
6.2 兼容性检查
26.x 提供滚动更新兼容性检查工具(kc.sh update-compatibility 子命令,官方标注 Preview):metadata 记录旧实例的配置元数据,check 判断当前配置是否可与旧元数据滚动共存,退出码 0 表示可滚动更新。多副本滚动升级前建议先跑该检查。
七、常见问题
Q1:up -d 后端口映射失败/服务不通? 检查宿主机 8080 是否被既有服务占用(本机实测 haproxy 占用 IPv4 8080):ss -tlnp | grep :8080;处理方式三选一——IPv6 栈发布([::]:8080:8080,本指南采用)、改 Keycloak 侧端口(KC_HTTP_PORT)、换宿主端口(8081:8080)。
Q2:Keycloak 一直重启,日志报 Connection to postgres refused? Keycloak 比 Postgres 先启动导致。必须用 depends_on + service_healthy(4.1 编排已含),并确认健康检查命令 pg_isready -U keycloak -d keycloak 与数据库账号匹配。
Q3:生产模式报 hostname is not configured 或 Key material not provided to setup HTTPS? 生产启动硬校验项,编排里必须有 KC_HOSTNAME 与 TLS 证书(或 KC_HTTP_ENABLED=true 交由前置代理终结 TLS),完整三步排障见《Keycloak 配置参数详解》6.2。
Q4:重建后用户与域全丢了? Postgres 数据目录没有做绑定挂载(或挂载路径写错),容器删除即丢库。确认 4.1 编排中 /opt/data/keycloak-pg:/var/lib/postgresql/data 存在,并按 4.3 的 down/up 闭环实测一次。
Q5:镜像 tag 该用 latest 还是固定版本? 生产编排固定版本号(本指南 26.8.1);latest 仅用于了解上游最新版本——本次拉取实测解析为 26.8.1,但随上游发布随时漂移,会造成"重建即升级"的不可控行为。
八、参考链接
- Keycloak 官方文档(Server Administration / Upgrading Guide):https://www.keycloak.org/documentation
- Keycloak 官方镜像与运行说明(quay.io):https://quay.io/repository/keycloak/keycloak
- Docker Compose 官方文档(compose 文件规范与 depends_on):https://docs.docker.com/compose/
- Postgres 16 官方镜像说明(初始化与环境变量):https://hub.docker.com/_/postgres
- 本专栏相关篇目:《Keycloak 配置参数详解》(KC_* 变量逐参数语义)、《Keycloak Admin API 使用详解》(部署完成后的管理操作)
- 相关文档:《Vaultwarden 1.37.4 Docker Compose 部署指南》《OpenBao Docker Compose 部署指南》