容器化环境下基于NGINX反向代理配置Kong与Keycloak:端口隐藏问题解决方案咨询
解决Kong + Keycloak + NGINX重定向暴露端口的问题
嘿,这个问题我之前帮不少人解决过——核心原因就是你的Kong和Keycloak不知道外部用户是通过NGINX的域名/端口访问的,所以它们生成重定向URL的时候直接用了容器内部的8000、8080端口。下面给你一步步拆解正确的配置方式:
一、先搞定NGINX:传递真实请求信息给后端
NGINX作为反向代理,必须把外部访问的域名、协议、端口这些关键信息传递给Kong和Keycloak,这样后端服务才能生成正确的外部URL。给你一个示例配置:
server { listen 80; server_name your-domain.com; # 替换成你的实际外部域名 # 转发请求到Kong的配置 location /api/ { proxy_pass http://kong:8000/; # kong是容器服务名,对应内部8000端口 # 传递真实请求头,让Kong知道外部访问的细节 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 告诉Kong外部用的是http/https proxy_set_header X-Forwarded-Port $server_port; # 传递外部访问的端口 } # 转发请求到Keycloak的配置(如果外部访问Keycloak也走NGINX) location /auth/ { proxy_pass http://keycloak:8080/; # keycloak是容器服务名,对应内部8080端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port; # Keycloak专属:处理路径前缀,避免生成错误的URL路径 proxy_set_header X-Forwarded-Context /auth; } }
二、配置Kong:指定外部访问地址
Kong需要明确知道用户从外部访问它的基础URL,这样OIDC插件生成的重定向回调地址才会正确。有两种配置方式:
方式1:容器启动时通过环境变量设置
在你的docker-compose.yml里给Kong添加环境变量:
services: kong: image: kong:latest environment: - KONG_PROXY_ACCESS_LOG=/dev/stdout - KONG_ADMIN_ACCESS_LOG=/dev/stdout - KONG_PROXY_ERROR_LOG=/dev/stderr - KONG_ADMIN_ERROR_LOG=/dev/stderr - KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl # 关键配置:外部用户访问Kong的完整地址 - KONG_PROXY_URL=http://your-domain.com/api/
方式2:通过Kong Admin API动态更新
如果Kong已经在运行,直接调用Admin API修改配置:
curl -X PATCH http://kong:8001/settings \ --data "proxy_url=http://your-domain.com/api/"
三、配置Keycloak:设置前端访问URL
Keycloak必须配置前端URL,否则它会默认用内部8080端口生成登录、重定向地址。同样有两种方式:
方式1:容器启动时通过环境变量设置
在docker-compose.yml里给Keycloak添加环境变量:
services: keycloak: image: quay.io/keycloak/keycloak:latest environment: - KEYCLOAK_ADMIN=admin - KEYCLOAK_ADMIN_PASSWORD=your-admin-pass - KC_PROXY=edge # 告诉Keycloak它运行在反向代理后面 - KC_HOSTNAME=your-domain.com # 外部域名 - KC_HOSTNAME_PATH=/auth # 对应NGINX里的/auth路径 - KC_HOSTNAME_PORT=80 # 外部端口(如果用HTTPS就是443) command: start
方式2:通过Keycloak控制台设置
- 通过NGINX访问Keycloak Admin控制台:
http://your-domain.com/auth/admin - 进入目标Realm的Realm Settings -> General
- 找到Frontend URL,设置为
http://your-domain.com/auth/ - 点击保存生效
四、调整Kong OIDC插件:用正确的回调地址
最后,确保OIDC插件的配置里,redirect_uri和discovery地址都用外部URL,而不是内部容器地址:
curl -X POST http://kong:8001/services/your-target-service/plugins \ --data "name=oidc" \ --data "config.client_id=your-kong-oidc-client" \ --data "config.client_secret=your-client-secret" \ --data "config.discovery=http://your-domain.com/auth/realms/your-realm/.well-known/openid-configuration" \ --data "config.redirect_uri=http://your-domain.com/api/your-protected-route/callback"
验证步骤
- 重启所有容器,确保配置都生效
- 访问受保护的API路径:
http://your-domain.com/api/your-protected-route - 检查重定向到Keycloak的URL,应该是
http://your-domain.com/auth/...(没有8080端口) - 登录成功后,重定向回Kong的URL应该是
http://your-domain.com/api/.../callback(没有8000端口)
如果还是有问题,可以排查这几点:
- NGINX的
proxy_set_header是否完整传递了所有头信息 - Kong的
proxy_url是否和外部访问路径完全匹配 - Keycloak的
KC_PROXY=edge是否配置,Frontend URL是否正确 - OIDC插件的
redirect_uri是否和外部访问路径一致
内容的提问来源于stack exchange,提问作者SoupriceCoder




