无法连接本地Docker中运行的Kestrel服务器求助
首先,我注意到你在启动容器时犯了一个关键的命令参数位置错误,这是导致502错误的主要原因。让我们一步步拆解问题并解决:
1. 修复Docker Run的端口映射参数位置
Docker Run的命令格式是:docker run [OPTIONS] IMAGE [COMMAND] [ARG...],其中--publish/-p属于Docker的启动选项,必须放在镜像名称前面。你现在把--publish-list 8000:8000或者--publish 8000:8000放在了镜像名hello-world-server后面,这些参数会被当成传给容器内.NET应用的启动参数,而不是Docker的端口映射配置——这就导致主机的8000端口根本没和容器的8000端口建立映射,自然访问http://localhost:8000会返回502。
正确的启动命令应该是:
docker run -p 8000:8000 hello-world-server
或者使用完整参数名:
docker run --publish 8000:8000 hello-world-server
2. 验证Kestrel监听配置的正确性
你的代码里用了UseUrls("http://+:8000"),这个配置是正确的——+表示监听容器内所有网络接口(等价于0.0.0.0),这样外部(主机)才能通过端口映射访问到Kestrel服务。如果Kestrel只监听localhost,那容器内部可以访问,但主机无法通过端口映射访问,不过你的代码这里没问题。
3. 优化日志输出以便排查
你提到Kestrel控制台没有请求日志,这是因为默认的WebHost.CreateDefaultBuilder在Production环境下(容器默认是Production)日志级别较高,不会输出请求日志。可以修改代码添加控制台日志支持:
static class Program { static void Main(string[] args) { var webHostBuilder = WebHost.CreateDefaultBuilder(args) .UseSetting("applicationName", "Hello World") // 添加控制台日志配置 .ConfigureLogging(logging => { logging.ClearProviders(); logging.AddConsole(); }) .Configure(builder => { builder.Run(async context => { var textBytes = System.Text.UTF8Encoding.UTF8.GetBytes("Hello World!"); await context.Response.Body.WriteAsync(textBytes, 0, textBytes.Length, default(System.Threading.CancellationToken)); }); }) .UseUrls("http://+:8000"); var webHost = webHostBuilder.Build(); webHost.Run(); } }
这样启动容器后,当有请求进来时,控制台会输出对应的日志,方便你确认请求是否到达了Kestrel。
4. 升级Docker基础镜像(可选但推荐)
你使用的microsoft/dotnet基础镜像比较老旧,微软已经把.NET镜像迁移到了mcr.microsoft.com仓库,建议换成对应.NET版本的官方镜像,比如如果是.NET 6,Dockerfile可以改成:
FROM mcr.microsoft.com/dotnet/runtime:6.0 WORKDIR /app ADD /application /app EXPOSE 8000 ENTRYPOINT [ "dotnet", "hello-world-server.dll" ]
旧镜像可能存在一些兼容性问题,升级后能获得更好的稳定性和安全性。
按照上面的步骤调整后,重新构建镜像并启动容器,应该就能正常访问http://localhost:8000并得到Hello World!的响应了。
内容的提问来源于stack exchange,提问作者BanksySan

