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

Docker Swarm下Nginx反向代理Keycloak非根路径Cookie异常排查

问题:Docker Swarm下Nginx反向代理/auth路径的Keycloak无法设置Cookie完成登录

我在Docker Swarm模式下将Keycloak容器部署在Nginx反向代理后的非根路径(/auth)下,当前Nginx同时代理了/backend后端服务和根路径的React服务。Keycloak可通过https://app.example.com/auth访问,但进入管理页面触发OAuth2登录流程时,浏览器无法设置Cookie;直接访问https://app.example.com:8443/则能正常设置Cookie并完成登录。相关配置如下:

用户配置

Dockerfile配置

FROM quay.io/keycloak/keycloak:latest as builder

# Enable health and metrics support
ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true

# Configure a database vendor
ENV KC_DB=mysql

WORKDIR /opt/keycloak

#Generating a Self-Signed Certificate
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:app.example.com" -keystore conf/server.keystore
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:latest
COPY --from=builder /opt/keycloak/ /opt/keycloak/

#change these values to point to a running Mysql instance
ENV KC_DB=mysql
ENV KC_DB_URL=jdbc:mysql://keycloak_database:3306/keycloak
ENV KC_DB_USERNAME=keycloak
ENV KC_DB_PASSWORD=keycloak
ENV KC_HOSTNAME_URL=https://app.example.com/auth/
ENV KC_HOSTNAME_ADMIN_URL=https://app.example.com/auth/
ENV KC_PROXY=edge
ENV KC_LOG_LEVEL=INFO
ENV KC_HOSTNAME_DEBUG=true
ENV KC_HOSTNAME_STRICT=false

ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

Keycloak服务启动命令

docker service create --name keycloak --network test_overlay --constraint node.labels.server==true --env KEYCLOAK_ADMIN=admin --env KEYCLOAK_ADMIN_PASSWORD=admin keycloakpro start --optimized

Nginx反向代理配置

server {
        listen 443 ssl;
        
        index index.html index.htm index.nginx-debian.html;

        server_name app.example.com;
        ssl_certificate /home/certificate.crt;
        ssl_certificate_key /home/private.key;
        
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        access_log /var/log/nginx/reverse-access.log;
        error_log /var/log/nginx/reverse-error.log;

        location /backend {
                    rewrite ^/backend(.*)$ $1 break;
                    proxy_pass http://backend-server:9999/;
                    proxy_redirect off;
        }
        
        location /auth {
                    rewrite ^/auth(.*)$ $1 break;
                    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 https;
                    proxy_set_header X-Forwarded-Host app.example.com;
                    proxy_set_header X-Forwarded-Port 8443;
                    proxy_pass https://keycloak:8443/;
                    add_header Set-Cookie $http_cookie;
       
        }
    
        location / {
                    rewrite ^/(.*)$ /$1 break;
                    proxy_pass http://react-server/;
                    proxy_http_version 1.1;
                    proxy_set_header Upgrade $http_upgrade;
                    proxy_set_header Connection ‘upgrade’;
                    proxy_cache_bypass $http_upgrade;

        }
        
    
}

server {
    listen 80;

    server_name app.example.com;

    return 301 https://$host$request_uri;
}

解决方案

1. 修正Keycloak环境变量,指定相对路径

Keycloak需要明确自身运行在/auth相对路径下,否则生成的Cookie路径为根路径/,与代理路径不匹配。修改Dockerfile中的环境变量:

# 移除末尾斜杠,添加相对路径配置
ENV KC_HOSTNAME_URL=https://app.example.com/auth
ENV KC_HOSTNAME_ADMIN_URL=https://app.example.com/auth
ENV KC_HTTP_RELATIVE_PATH=/auth

2. 修复Nginx代理的Cookie路径与端口配置

当前Nginx的X-Forwarded-Port设置错误,且手动添加Set-Cookie头会干扰Keycloak的原生Cookie设置。修改location /auth块:

location /auth {
    rewrite ^/auth(.*)$ $1 break;
    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 https;
    proxy_set_header X-Forwarded-Host app.example.com;
    proxy_set_header X-Forwarded-Port 443; # 改为用户实际访问的443端口
    proxy_pass https://keycloak:8443/;
    # 移除错误的add_header Set-Cookie配置
    # 将Keycloak返回的Cookie路径从/映射到/auth/
    proxy_cookie_path / /auth/;
}

3. 重启服务生效

  • 重新构建Keycloak镜像:
docker build -t keycloakpro .
  • 更新Docker Swarm中的Keycloak服务:
docker service update --image keycloakpro keycloak
  • 重启Nginx服务:
systemctl restart nginx

原理说明

  • KC_HTTP_RELATIVE_PATH=/auth让Keycloak知道自身部署在/auth路径下,生成的所有URL和Cookie都会适配该路径。
  • proxy_cookie_path / /auth/将Keycloak返回的Cookie路径从根路径/替换为/auth/,确保浏览器在访问/auth路径时会携带该Cookie。
  • X-Forwarded-Port=443修正了端口信息,Keycloak会基于正确的端口生成Cookie的属性,避免端口不匹配导致Cookie无法保存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 07:37:17