Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 控制托管在docker中的.NET核心控制台应用程序的生存期_C#_Linux_Docker_<img Src="//i.stack.imgur.com/WM7S8.png" Height="16" Width="18" Alt="" Class="sponsor Tag Img">servicestack_.net Core - Fatal编程技术网 servicestack,.net-core,C#,Linux,Docker,servicestack,.net Core" /> servicestack,.net-core,C#,Linux,Docker,servicestack,.net Core" />

C# 控制托管在docker中的.NET核心控制台应用程序的生存期

C# 控制托管在docker中的.NET核心控制台应用程序的生存期,c#,linux,docker,servicestack,.net-core,C#,Linux,Docker,servicestack,.net Core,免责声明-这几乎是同一个问题-但我不认为在这个问题上接受的答案是令人满意的 我正在努力实现的目标 我正在构建一个控制台应用程序(它是一个使用ServiceStack的HTTP服务),它是用.NET核心构建的(dnxcore50-这是一个控制台应用程序,而不是ASP.NET应用程序)。我正在Linux机器上的docker容器中运行此应用程序。我已经这样做了,HTTP服务可以正常工作 我的问题 说了“我的服务有效”——它确实有效,但在docker容器中托管服务存在问题。启动HTTP侦听器后,我使用的

免责声明-这几乎是同一个问题-但我不认为在这个问题上接受的答案是令人满意的

我正在努力实现的目标
我正在构建一个控制台应用程序(它是一个使用ServiceStack的HTTP服务),它是用.NET核心构建的(dnxcore50-这是一个控制台应用程序,而不是ASP.NET应用程序)。我正在Linux机器上的docker容器中运行此应用程序。我已经这样做了,HTTP服务可以正常工作

我的问题
说了“我的服务有效”——它确实有效,但在docker容器中托管服务存在问题。启动HTTP侦听器后,我使用的是
Console.ReadLine()
,但此代码不会在docker容器中阻塞,启动后容器将立即退出。我可以在“交互式”模式下启动docker容器,服务将坐在那里监听,直到我终止交互式会话,然后容器将退出

回购代码
下面的代码是创建我的test.NET core servicestack控制台应用程序的完整代码列表

public class Program
{
    public static void Main(string[] args)
    {
        new AppHost().Init().Start("http://*:8088/");
        Console.WriteLine("listening on port 8088");
        Console.ReadLine();

    }
}

public class AppHost : AppSelfHostBase
{
    // Initializes your AppHost Instance, with the Service Name and assembly containing the Services
    public AppHost() : base("My Test Service", typeof(MyTestService).GetAssembly()) { }

    // Configure your AppHost with the necessary configuration and dependencies your App needs
    public override void Configure(Container container)
    {

    }
}

public class MyTestService: Service
{
    public TestResponse Any(TestRequest request)
    {
        string message = string.Format("Hello {0}", request.Name);
        Console.WriteLine(message);
        return new TestResponse {Message = message};
    }

}

[Api("Test method")]
[Route("/test/{Name}", "GET", Summary = "Get Message", Notes = "Gets a message incorporating the passed in name")]
public class TestRequest : IReturn<TestResponse>
{
    [ApiMember(Name = "Name", Description = "Your Name", ParameterType = "path", DataType = "string")]
    public string Name { get; set; }
}

public class TestResponse 
{
    [ApiMember(Name = "Message", Description = "A Message", ParameterType = "path", DataType = "string")]
    public string Message { get; set; }
}
现在-我知道这对.NETCore不起作用(显然是因为Mono.Posix是针对Mono的!)

相关文章(本文顶部)中概述的解决方案对我没有用处-在生产环境中,我不能期望通过确保docker容器具有可使Console.ReadLine保持工作的交互式会话来保持其活动,因为那里有STD-in流

托管.NET核心应用程序时,是否有其他方法保持docker容器的活动状态(在调用
docker run
时使用
-d
(分离)选项)

代码重构是Mythz建议的一部分

 public static void Main(string[] args)
    {
        Run(new AppHost().Init(), "http://*:8088/");
    }

    public static void Run(ServiceStackHost host, params string[] uris)
    {
        AppSelfHostBase appSelfHostBase = (AppSelfHostBase)host;

        using (IWebHost webHost = appSelfHostBase.ConfigureHost(new WebHostBuilder(), uris).Build())
        {
            ManualResetEventSlim done = new ManualResetEventSlim(false);
            using (CancellationTokenSource cts = new CancellationTokenSource())
            {
                Action shutdown = () =>
                {
                    if (!cts.IsCancellationRequested)
                    {
                        Console.WriteLine("Application is shutting down...");
                        cts.Cancel();
                    }

                    done.Wait();
                };

                Console.CancelKeyPress += (sender, eventArgs) =>
                {
                    shutdown();
                    // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
                    eventArgs.Cancel = true;
                };

                Console.WriteLine("Application started. Press Ctrl+C to shut down.");
                webHost.Run(cts.Token);
                done.Set();
            }
        }
    }
最终解决方案

 public static void Main(string[] args)
    {
        Run(new AppHost().Init(), "http://*:8088/");
    }

    public static void Run(ServiceStackHost host, params string[] uris)
    {
        AppSelfHostBase appSelfHostBase = (AppSelfHostBase)host;

        using (IWebHost webHost = appSelfHostBase.ConfigureHost(new WebHostBuilder(), uris).Build())
        {
            ManualResetEventSlim done = new ManualResetEventSlim(false);
            using (CancellationTokenSource cts = new CancellationTokenSource())
            {
                Action shutdown = () =>
                {
                    if (!cts.IsCancellationRequested)
                    {
                        Console.WriteLine("Application is shutting down...");
                        cts.Cancel();
                    }

                    done.Wait();
                };

                Console.CancelKeyPress += (sender, eventArgs) =>
                {
                    shutdown();
                    // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
                    eventArgs.Cancel = true;
                };

                Console.WriteLine("Application started. Press Ctrl+C to shut down.");
                webHost.Run(cts.Token);
                done.Set();
            }
        }
    }
对于子孙后代-我的解决方案是可以在这里找到的代码(感谢神话的澄清):

相关代码的回购:

public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup<Startup>()
            .UseUrls("http://*:8088/")
            .Build();

        host.Run();
    }
}

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // app.UseStaticFiles();

        app.UseServiceStack(new AppHost());

        app.Run(context =>
        {
            context.Response.Redirect("/metadata");
            return Task.FromResult(0);
        });
    }
publicstaticvoidmain(字符串[]args)
{
var host=new WebHostBuilder()
.UseKestrel()
.UseContentRoot(目录.GetCurrentDirectory())
.UseStartup()
.useURL(“http://*:8088/”)
.Build();
host.Run();
}
}
公营创业
{
//此方法由运行时调用。请使用此方法将服务添加到容器中。
public void配置服务(IServiceCollection服务)
{
}
//此方法由运行时调用。请使用此方法配置HTTP请求管道。
公共无效配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
//app.UseStaticFiles();
app.UseServiceStack(新的AppHost());
app.Run(上下文=>
{
context.Response.Redirect(“/metadata”);
返回Task.FromResult(0);
});
}

在NuGet中,我安装了Microsoft.NETCore.App、ServiceStack.Core和ServiceStack.Kestrel。

如果您要在Docker中托管.NET Core应用程序,我建议您只遵循调用
IWebHost.Run()
的正常操作,以阻止主线程并使控制台应用程序保持活动状态


AppHostSelfBase只是一个函数,但调用非阻塞的
IWebHost.Start()
。以获取
IWebHost.Run()的行为
您应该能够重复使用
ManualResetEventSlim
Console.CancelKeyPress
的相同方法,但就个人而言,使用.NET Core的托管API和调用
Run()
和just更容易。

我尝试过将代码用作(我想)您已经建议-它似乎在Windows和我的Linux Docker中都能工作…更新是针对我的原始问题的-在文章的底部。您认为解决方案如何?我是否理解正确?@Jay如果它能工作,我肯定它很好,但为什么不使用.NET Core推荐的托管模式?不清楚您为什么要使用它可能是因为我还不了解:)我是一个完全的.NET内核的noob,真的不明白这里的示例:在Linux中如何工作;
useisintegration()
do in a Linux container,以及如何设置我想要监听的端口。我已经习惯于使用ServiceStack创建简单的自托管控制台应用程序-我想要的是与以前几乎相同的东西。也许我需要更多地阅读一下.NET core和托管模型。@Jay.NET core中的所有应用程序都是自托管的ole应用程序和使用集成()在Linux上被忽略,因此您可以忽略/删除它。您不需要了解.NET Core托管模型,只需保持原样,它所做的主要工作是指向您的自定义启动类并侦听您指定的URL。请查看现有的.NET Core Live Demo,其中包含ServiceStack现有Live De的小型独立示例mos.@Jay还介绍了每个.NET核心示例在Windows和Linux上的运行情况。它们都托管在Linux/Docker上,并使用每个repo中包含的部署脚本与AWS ECS一起部署,如本分步指南所述: