Docker容器中无法启动Kestrel服务的问题求助
这个问题我之前排查过好几次,核心原因其实很明确:你在Kestrel配置里指定绑定的172.16.63.250,并不是Docker容器内部的可用IP地址。
为什么会出现这个错误?
当你在CentOS宿主机的bash环境中直接运行应用时,172.16.63.250是宿主机网卡上的有效IP,所以Kestrel能成功绑定。但Docker容器默认使用桥接网络模式,每个容器会被分配一个属于Docker专属子网的独立IP(比如常见的172.17.x.x段),容器内部的网卡根本没有172.16.63.250这个地址,自然会报"address not available"。
而且你提到容器能正常连接同一子网的Redis、MongoDB,这只能说明容器的网络连通性没问题,但不代表容器能直接使用宿主机或其他机器的IP来绑定监听。
具体解决方案
这里有两种可行的解决思路,推荐优先用第一种:
1. 绑定到容器所有可用接口(最推荐)
修改你的BuildWebHost方法中的UseUrls配置,把指定的IP替换成0.0.0.0,这样Kestrel会监听容器内部所有网络接口:
private static IWebHost BuildWebHost(string hostAddress) { return new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseSerilog() .ConfigureAppConfiguration((builderContext, config) => { config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); }) .UseDefaultServiceProvider((context, options) => { options.ValidateScopes = context.HostingEnvironment.IsDevelopment(); }) .UseStartup<Startup>() // 把指定IP换成0.0.0.0 .UseUrls($"http://0.0.0.0:{ServerPort}") .Build(); }
同时修改Dockerfile的ENTRYPOINT,不需要再传入那个IP参数了:
ENTRYPOINT ["dotnet", "OperationsManagerServer.dll", "/logs"]
启动容器时,通过端口映射把容器内的ServerPort暴露给宿主机:
docker run -p 宿主机端口:容器内ServerPort 你的镜像名称
这样外部就能通过宿主机IP:宿主机端口访问应用,容器内部和Redis、MongoDB的通信也不会受影响。
2. 给容器分配固定IP(仅当必须绑定特定IP时使用)
如果你业务上必须绑定172.16.63.250这个IP,可以创建自定义Docker网络并给容器分配固定IP:
首先创建自定义子网:
docker network create --subnet=172.16.63.0/24 my-app-network
然后启动容器时指定这个网络和固定IP:
docker run --network my-app-network --ip 172.16.63.250 你的镜像名称
这种方式需要确保172.16.63.250在你创建的子网范围内,且没有被其他容器占用。不过这种方案灵活性较差,不如第一种通用。
内容的提问来源于stack exchange,提问作者ThommyB

