Docker容器间Keycloak与Spring Boot认证失败问题求助
看起来你遇到了Docker容器间网络通信的典型问题——虽然两个服务在同一个docker-compose里,但Spring Boot容器没法正确访问Keycloak。我来帮你一步步排查解决:
问题核心原因
你在宿主机能通过localhost:18080访问Keycloak,是因为Docker把Keycloak容器的8080端口映射到了宿主机的18080。但Spring Boot容器内部的localhost指的是它自己的容器,不是宿主机,更不是Keycloak容器。所以你之前在Spring Boot配置里写的Keycloak地址如果是http://localhost:18080/auth,容器根本找不到对应的服务,自然报IO错误。
分步解决办法
1. 修正Spring Boot的Keycloak配置
打开你的application-developmentTest.yml(或application.properties),把Keycloak的认证地址改成Docker Compose里的Keycloak服务名keycloak,端口用容器内部的8080(容器间通信不用宿主机的映射端口):
# YAML配置示例 keycloak: auth-server-url: http://keycloak:8080/auth realm: 你的Realm名称 resource: 你的客户端ID credentials: secret: 你的客户端密钥
如果是properties格式:
# Properties配置示例 keycloak.auth-server-url=http://keycloak:8080/auth keycloak.realm=你的Realm名称 keycloak.resource=你的客户端ID keycloak.credentials.secret=你的客户端密钥
2. 验证容器间的连通性
先进入Spring Boot容器,直接测试能不能访问Keycloak:
# 替换成你的Spring Boot容器名称 docker exec -it mySpringBootApp sh # 访问Keycloak的OpenID配置端点,测试连通性 curl http://keycloak:8080/auth/realms/你的Realm名称/.well-known/openid-configuration
如果能返回一段JSON配置,说明网络通了,接下来重启Spring Boot容器应该就能正常认证了。
3. 确保Keycloak完全就绪后再启动Spring Boot
depends_on只是保证容器启动顺序,但Keycloak启动需要加载配置和初始化,可能比Spring Boot慢。可以给Keycloak加个健康检查,让Spring Boot等Keycloak完全就绪再启动:
修改docker-compose里的Keycloak配置:
keycloak: image: jboss/keycloak ports: - 18080:8080 volumes: - ../keycloak:/opt/jboss/keycloak/imports command: - "-b 0.0.0.0 -Dkeycloak.import=/opt/jboss/keycloak/imports/realm-export.json" environment: - KEYCLOAK_USER=admin - KEYCLOAK_PASSWORD=admin healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/auth/realms/master"] interval: 10s timeout: 5s retries: 5
然后修改Spring Boot的depends_on,让它等Keycloak健康检查通过:
mySpringBootApp: image: mySpringBootApp:master-1 environment: - SPRING_PROFILES_ACTIVE=developmentTest depends_on: jaeger: condition: service_started keycloak: condition: service_healthy db: condition: service_started ports: - "8081:8081"
4. 额外检查:Keycloak客户端的跨域设置(如果涉及前端访问)
如果你的前端也需要访问Keycloak,记得在Keycloak的客户端配置里,把Web Origins设置成允许的地址(比如http://localhost:8081,测试阶段可以暂时设为*),避免跨域问题影响认证流程。
补充:为什么本地运行正常?
本地跑Spring Boot Jar的时候,你的代码是在宿主机上运行的,localhost指向宿主机,而Keycloak容器的端口映射到了宿主机的18080,所以能正常访问。但容器内的网络是隔离的,必须用Docker服务名来访问同一网络下的其他容器。
内容的提问来源于stack exchange,提问作者Kristjan




