docker容器即使在.net核心控制台应用程序中使用Console.ReadLine()也会立即退出
我正在尝试在Docker容器中运行.net核心1.0.0控制台应用程序。
当我从我的机器上的Demo文件夹内运行dotnet run
命令时,它工作正常; 但是使用docker run -d --name demo Demo
时,容器会立即退出。
我试着docker logs demo
检查日志,它只是显示Console.WriteLine文本:
演示程序运行…
没有别的。
我已经在https://github.com/learningdockerandnetcore/Demo上传了这个项目
该项目包含Programs.cs
,用于创build演示图像的Dockerfile
和project.json
文件。
您应该以交互模式运行容器(使用-i
选项)。 但请注意,后台进程将在运行容器时立即closures,因此请确保脚本在前台运行,否则将无法工作。
让Docker / Linux保持我的.NET Core应用程序活着的唯一方法就是欺骗ASP.NET来为我托pipe它…这真是一个丑陋的黑客!
这样做将在Docker中使用docker run -d
选项docker run -d
,因此您不必拥有一个实时连接来保持STDINstream的活性。
我创build了一个.NET Core控制台应用程序(不是一个ASP.NET应用程序),我的程序类看起来像这样:
public class Program { public static ManualResetEventSlim Done = new ManualResetEventSlim(false); public static void Main(string[] args) { //This is unbelievably complex because .NET Core Console.ReadLine() does not block in a docker container...! var host = new WebHostBuilder().UseStartup(typeof(Startup)).Build(); 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; }; host.Run(cts.Token); Done.Set(); } } }
启动类:
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IServer, ConsoleAppRunner>(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { } }
ConsoleAppRunner类
public class ConsoleAppRunner : IServer { /// <summary>A collection of HTTP features of the server.</summary> public IFeatureCollection Features { get; } public ConsoleAppRunner(ILoggerFactory loggerFactory) { Features = new FeatureCollection(); } /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary> public void Dispose() { } /// <summary>Start the server with an application.</summary> /// <param name="application">An instance of <see cref="T:Microsoft.AspNetCore.Hosting.Server.IHttpApplication`1" />.</param> /// <typeparam name="TContext">The context associated with the application.</typeparam> public void Start<TContext>(IHttpApplication<TContext> application) { //Actual program code starts here... Console.WriteLine("Demo app running..."); Program.Done.Wait(); // <-- Keeps the program running - The Done property is a ManualResetEventSlim instance which gets set if someone terminates the program. } }
唯一的好处就是你可以在应用程序中使用DI(如果你愿意的话) – 所以在我的用例中,我使用ILoggingFactory来处理日志。
另一个“肮脏的方式”是在屏幕上使用开始你的程序
screen -dmS yourprogramm
我不知道为什么Console.ReadLine();
在分离的ConsoleCancelEventHandler
容器中运行dotnet核心控制台应用程序时,不阻止主线程,但最好的解决scheme是使用Console.CancelKeyPress
事件注册ConsoleCancelEventHandler
。
然后你可以用一个线程WaitHandle
来阻塞主线程,并在Console.CancelKeyPress
被触发时发出主线程的释放信号。
一个很好的示例代码可以在这里find: https : //gist.github.com/kuznero/73acdadd8328383ea7d5
您可以使用:
Thread.Sleep(Timeout.Infinite);
看到这个答案:
是Thread.Sleep(Timeout.Infinite); 比while(true){}更有效率?
- 在dotnet发布后,在docker映像中找不到Application Insights依赖关系
- AWS Codebuild .NET Core构buildDocker镜像
- dotnet运行不会使用bower软件包
- VSCode在连接到Windows泊坞窗容器上的远程debugging器时挂起在断点上
- 在Docker-image microsoft / aspnetcore-build:1.1.0-msbuild中构buildASP.NET Core 1.1 preview4项目
- Dotnet Core从Mac发布到IIS
- Identity Server 4和Docker
- Docker与.NET Core无法联系
- Dotnet core 2 docker:找不到可执行的匹配命令“dotnet-watch”