Docker Compose下Keycloak与Spring Boot应用连接被拒绝问题
解决方案
核心问题拆解
- 容器间通信逻辑:Spring Boot容器与Keycloak容器处于同一Docker网络时,必须使用服务名/容器网络内地址通信,容器内的
localhost仅指向自身,无法访问宿主机或其他容器。 - Issuer URI双重需求:Spring Boot内部做JWT验证时,需要访问Keycloak的容器内地址;而浏览器端的OAuth2授权流程,需要访问Keycloak的宿主机映射地址,且Keycloak自身返回的Issuer地址必须与浏览器可访问的地址一致。
步骤1:修正Docker Compose配置
确保两个容器处于同一网络(默认default网络即可,也可自定义),同时给Keycloak配置正确的对外主机名和端口映射:
version: '3.8' services: keycloak: image: quay.io/keycloak/keycloak:22.0.3 environment: - KC_DB=postgres - KC_DB_URL=jdbc:postgresql://postgres:5432/keycloak - KC_DB_USERNAME=keycloak - KC_DB_PASSWORD=password - KC_HOSTNAME=localhost # 与浏览器访问Keycloak的主机名一致 - KC_HOSTNAME_PORT=8090 # 宿主机映射的Keycloak端口 - KC_HTTP_PORT=8080 # Keycloak容器内部端口 - KC_ADMIN=admin - KC_ADMIN_PASSWORD=admin ports: - "8090:8080" networks: - app-network depends_on: - postgres # 若未用PostgreSQL可删除该依赖 spring-boot-app: build: . environment: - SPRING_PROFILES_ACTIVE=docker - KEYCLOAK_ISSUER_INTERNAL=http://keycloak:8080/realms/ShootingStar # 容器间通信用服务名+内部端口 - KEYCLOAK_ISSUER_EXTERNAL=http://localhost:8090/realms/ShootingStar # 外部浏览器访问的地址 ports: - "8081:8080" # 自定义Spring Boot宿主机映射端口 networks: - app-network depends_on: - keycloak networks: app-network: driver: bridge
步骤2:调整Spring Boot配置
创建application-docker.yml(对应上述docker环境配置),区分内部验证与外部授权的Issuer地址:
spring: security: oauth2: # 资源服务器配置:内部JWT验证用容器内地址 resourceserver: jwt: issuer-uri: ${KEYCLOAK_ISSUER_INTERNAL} # OAuth2客户端配置:前端授权流程用外部地址 client: provider: keycloak: issuer-uri: ${KEYCLOAK_ISSUER_EXTERNAL} registration: keycloak: client-id: your-client-id client-secret: your-client-secret scope: openid,profile,email
如果你的应用仅作为资源服务器(无前端OAuth2跳转),只需保留resourceserver.jwt.issuer-uri配置即可。
步骤3:验证配置有效性
- 启动容器:
docker-compose up -d - 检查Spring Boot容器日志,确认无连接拒绝报错
- 浏览器访问
http://localhost:8090/realms/ShootingStar/.well-known/openid-configuration,确认返回正常的OpenID配置 - 访问Spring Boot应用接口(如
http://localhost:8081/api/xxx),验证JWT授权流程正常
常见避坑点
- 禁止直接将Issuer URI设为
localhost:8090:容器内的localhost指向自身,无法访问Keycloak容器 - 必须配置Keycloak的
KC_HOSTNAME:否则Keycloak返回的Issuer地址会是容器内部的keycloak:8080,浏览器无法识别导致授权失败 - 验证容器网络连通性:执行
docker exec -it <spring-boot-container-name> ping keycloak,测试容器间是否能通过服务名访问Keycloak
内容的提问来源于stack exchange,提问作者Ackon Peter Jude
相关产品推荐
相关产品推荐

