Docker化Duende Identity Server时配置获取失败问题求助
问题描述
我正在将一个微服务架构的个人项目Docker化,项目包含多个微服务、客户端和Duende Identity Server。本地环境下,客户端可直接与Duende Identity Server通信:点击登录会跳转至Identity Server完成注册或认证,之后返回客户端并携带授权Cookie。但Docker化后遇到两个矛盾的问题:
- 配置客户端连接
localhost的Identity Server时,会报错:Unable to obtain configuration from: 'https://localhost:44384/.well-known/openid-configuration'. Connection refused,但手动在浏览器访问该链接能正常获取JSON响应。 - 配置成Docker内部地址
https://app.service.identity时,浏览器会跳转至仅Docker内部可访问的链接,导致页面找不到。
相关配置文件
docker-compose.yml
x-app-default-env: &app-default-env Logging__LogLevel__Default: Information Logging__LogLevel__Microsoft.AspNetCore: Warning AllowedHosts: "*" services: app: restart: unless-stopped image: mango.web build: context: ./Mango.Web volumes: - ./Mango.Web/wwwroot:/app/wwwroot environment: <<: *app-default-env ServiceUrls__IdentityAPI: https://localhost:44384 ServiceUrls__ProductAPI: http://app.service.product ServiceUrls__CouponAPI: http://app.service.coupon ServiceUrls__ShoppingCartAPI: http://app.service.shoppingcart ServiceUrls__AzureBlobAPI: ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoWEBAPI" app.service.order: restart: unless-stopped image: mango.services.order build: context: . dockerfile: ./Mango.Services.OrderAPI/Dockerfile environment: <<: *app-default-env ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoOrderAPI" ConnectionStrings__AzureServiceBus: ${AZURE_SERVICE_BUS_CONNECTION_STRING} CheckoutMessageTopic: "checkoutmessagetopic" CheckoutSubscription: "mangoOrdersSubscription" OrderPaymentProcessTopic: "orderpaymentprocesstopic" OrderPaymentProcessSubscription: "mangoPayment" OrderUpdatePaymentResultTopic: "orderupdatepaymentresulttopic" OrderUpdatePaymentResultSubscription": "mangoOrdersSubscription" CheckoutMessageQueue: "checkoutqueue" app.service.azureblobservice: restart: unless-stopped image: mango.services.azureblobservice build: Mango.Services.AzureBlobService environment: <<: *app-default-env ServiceUrls__IdentityServer: http://app.service.identity ConnectionStrings__BlobStorage: ${CONNECTION_STRINGS_BLOB_STORAGE} BlobContainerName: ${BLOB_CONTAINER_NAME} app.service.product: restart: unless-stopped image: mango.services.productapi build: Mango.Services.ProductAPI environment: <<: *app-default-env ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoProductAPI" app.service.payment: restart: unless-stopped image: mango.services.payment build: context: . dockerfile: ./Mango.Services.PaymentAPI/Dockerfile environment: <<: *app-default-env ServiceUrls__IdentityServer: http://app.service.identity ConnectionStrings__AzureServiceBus: ${AZURE_SERVICE_BUS_CONNECTION_STRING} OrderPaymentProcessTopic: "orderpaymentprocesstopic" OrderPaymentProcessSubscription: "mangoPayment" OrderUpdatePaymentResultTopic: "orderupdatepaymentresulttopic" OrderUpdatePaymentResultSubscription: "mangoOrdersSubscription" ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoPaymentAPI" app.service.shoppingcart: restart: unless-stopped image: mango.services.shoppingcart build: context: . dockerfile: ./Mango.Services.ShoppingCartAPI/Dockerfile environment: <<: *app-default-env ServiceUrls__IdentityServer: http://app.service.identity ServiceUrls__CouponAPI: http://app.service.coupon ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoShoppingCartAPI" app.service.identity: restart: unless-stopped image: mango.services.identity build: Mango.Services.Identity volumes: - ./Mango.Services.Identity/wwwroot:/app/wwwroot environment: <<: *app-default-env ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoIdentityAPI" app.service.email: restart: unless-stopped image: mango.services.email build: context: . dockerfile: ./Mango.Services.Email/Dockerfile environment: <<: *app-default-env ConnectionStrings__AzureServiceBus: ${AZURE_SERVICE_BUS_CONNECTION_STRING} OrderUpdatePaymentResultTopic: "orderupdatepaymentresulttopic" EmailSubscription: "emailSubscription" ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoEmailAPI" app.service.coupon: restart: unless-stopped image: mango.services.coupon build: Mango.Services.CouponAPI environment: <<: *app-default-env ServiceUrls__IdentityServer: ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoCouponAPI"
docker-compose.override.yml
services: app: ports: - 8080:80 - 44315:443 environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=https://+:443;http://+:80 - ASPNETCORE_Kestrel__Certificates__Default__Password=password - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx volumes: - ~/.aspnet/https:/https:ro app.service.identity: ports: - 44384:443 - 8081:80 environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=https://+:443;http://+:80 - ASPNETCORE_Kestrel__Certificates__Default__Password=password - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx volumes: - ~/.aspnet/https:/https:ro db: restart: unless-stopped ports: - 5433:5432 image: postgres:16 user: root volumes: - ../docker/db/data:/var/lib/pgsql/data environment: POSTGRES_PASSWORD: postgres POSTGRES_USER: postgres
Client Program.cs 授权配置
builder.Services.AddAuthentication(options => { options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "oidc"; }).AddCookie("Cookies", c => c.ExpireTimeSpan=TimeSpan.FromMinutes(10)) .AddOpenIdConnect("oidc", options => { options.Authority = builder.Configuration["ServiceUrls:IdentityAPI"]; options.GetClaimsFromUserInfoEndpoint = true; options.ClientId = "mango"; options.ClientSecret = "secret"; options.ResponseType = "code"; options.ClaimActions.MapJsonKey("role", "role", "role"); options.ClaimActions.MapJsonKey("sub", "sub", "sub"); options.TokenValidationParameters.NameClaimType = "name"; options.TokenValidationParameters.RoleClaimType = "role"; options.Scope.Add("mango"); options.SaveTokens = true; options.RequireHttpsMetadata = false; options.BackchannelHttpHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true }; });
解决方案
核心矛盾是容器内服务和外部浏览器访问Identity Server的地址不一致:容器内的客户端服务需要用Docker内部域名访问,而浏览器必须用宿主机的公开地址访问。按以下步骤调整即可解决:
1. 给Identity Server配置公开访问地址
在docker-compose.override.yml的app.service.identity环境变量中,添加公开地址配置,让Duende Identity Server生成浏览器能访问的跳转地址:
app.service.identity: # 原有配置保留 environment: # 新增这一行 - IdentityServer__PublicOrigin=https://localhost:44384
2. 调整客户端服务的Identity Server地址
把docker-compose.yml中app服务的ServiceUrls__IdentityAPI改成Docker内部域名,让容器内的客户端服务能正常连通Identity Server:
app: environment: # 把原有的localhost地址改成内部域名 ServiceUrls__IdentityAPI: https://app.service.identity:443 # 其他配置保留
3. 修正Identity Server的客户端配置
在Duende Identity Server的客户端注册代码中,确保回调地址、注销地址用宿主机的公开地址,比如:
new Client { ClientId = "mango", ClientSecret = "secret", // 对应app服务在宿主机的HTTPS端口44315 RedirectUris = { "https://localhost:44315/signin-oidc" }, PostLogoutRedirectUris = { "https://localhost:44315/signout-callback-oidc" }, // 其他配置保留 }
4. 验证容器间连通性(可选)
如果还是有问题,可进入客户端容器测试内部网络:
# 替换成你的app容器ID docker exec -it <app-container-id> bash # 测试访问Identity Server内部地址 curl https://app.service.identity:443/.well-known/openid-configuration
能返回JSON说明容器内网络正常。
内容的提问来源于stack exchange,提问作者SilverMoon17
相关产品推荐
相关产品推荐

