Docker中Keycloak搭配Nginx代理使用非标准端口的配置求助
解决Keycloak在Docker+反向代理(Nginx/Traefik)下非标准HTTPS端口的无限加载问题
问题背景
原本用Docker Compose搭配Nginx部署Keycloak并启用TLS,使用443标准端口时,注释掉KC_HOSTNAME_PORT就能正常运行;但改用8443这类非标准端口后,打开KC_HOSTNAME_PORT配置就会出现前端无限加载转圈的问题。
核心原因
Keycloak需要准确感知外部访问的端口,若反向代理未正确传递包含端口的Host头,或者Keycloak的端口配置与外部访问端口不匹配,会导致Keycloak生成的前端资源路径、重定向地址错误,最终引发加载失败。
解决方案一:Nginx + Docker Compose完整配置
1. Docker Compose配置文件(docker-compose.yml)
version: '3' services: keycloak: image: quay.io/keycloak/keycloak:19.0.2 container_name: keycloak environment: KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin KC_PROXY: 'edge' KC_PROXY_ADDRESS_FORWARDING: 'true' KC_HOSTNAME: kvm1.home KC_HOSTNAME_PORT: 8443 # 与外部访问的非标准HTTPS端口保持一致 KC_HOSTNAME_STRICT: 'false' KC_HTTP_ENABLED: 'true' ports: - "8080:8080" command: - start-dev - "--proxy=edge" - "--hostname-strict-https=true" # 外部用HTTPS,强制生成HTTPS链接 nginx: image: nginx:1.23.1 container_name: nginx volumes: - ./ssl:/etc/nginx/ssl - ./sites-enabled:/etc/nginx/sites-enabled - ./nginx.conf:/etc/nginx/nginx.conf:rw ports: - "80:80" - "8443:443" # 外部8443端口映射到容器内443端口 environment: - NGINX_HOST=kvm1.home
2. Nginx站点配置文件(sites-enabled/keycloak.conf)
server { listen 443 ssl; listen [::]:443 ssl; ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/privkey.pem; server_name kvm1.home; location / { proxy_pass http://keycloak:8080/; # 用Docker容器名访问,避免依赖宿主机IP proxy_set_header Host $host:$server_port; # 关键:传递包含端口的完整Host头 proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port; # 辅助Keycloak识别外部端口 } # 可选:将HTTP请求强制跳转至HTTPS listen 80; listen [::]:80; return 301 https://$host:$server_port$request_uri; }
关键配置说明
- Keycloak侧:
KC_HOSTNAME_PORT必须和外部实际访问的HTTPS端口完全一致;KC_HOSTNAME_STRICT_HTTPS设为true,确保所有前端资源链接都是HTTPS协议。 - Nginx侧:
proxy_set_header Host $host:$server_port是解决问题的核心,必须把包含端口的Host头传递给Keycloak,否则Keycloak无法识别外部访问端口,生成的资源路径会出错。
解决方案二:Traefik + Docker Compose完整配置
如果偏好使用Traefik作为反向代理,可直接用以下配置(自动管理SSL证书):
version: '3' services: keycloak: image: quay.io/keycloak/keycloak:19.0.2 container_name: keycloak environment: KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin KC_PROXY: 'edge' KC_PROXY_ADDRESS_FORWARDING: 'true' KC_HOSTNAME: kvm1.home KC_HOSTNAME_PORT: 8443 KC_HOSTNAME_STRICT: 'false' KC_HTTP_ENABLED: 'true' command: - start-dev - "--proxy=edge" - "--hostname-strict-https=true" labels: - "traefik.enable=true" - "traefik.http.routers.keycloak.rule=Host(`kvm1.home`)" - "traefik.http.routers.keycloak.entrypoints=websecure" - "traefik.http.routers.keycloak.tls.certresolver=myresolver" - "traefik.http.services.keycloak.loadbalancer.server.port=8080" traefik: image: traefik:v2.9 container_name: traefik command: - "--api.insecure=true" # 开发环境开启API面板,生产环境建议关闭 - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:8443" - "--certificatesresolvers.myresolver.acme.httpchallenge=true" - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web" - "--certificatesresolvers.myresolver.acme.email=your-email@example.com" # 替换为你的邮箱 - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" ports: - "80:80" - "8443:8443" - "8080:8080" # Traefik API面板访问端口 volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" - "./letsencrypt:/letsencrypt"
Traefik配置说明
- Traefik通过Let's Encrypt自动生成和管理SSL证书,无需手动配置证书文件。
- Keycloak的
KC_HOSTNAME_PORT与Traefik的websecure入口端口保持一致(8443)。 - Traefik会自动向Keycloak传递
X-Forwarded-*系列头,符合Keycloak的edge代理模式要求。
内容的提问来源于stack exchange,提问作者Joseph Dalton
相关产品推荐
相关产品推荐

