2016-07-24 9 views
7

ドッキングコンテナ内で.netコア1.0.0コンソールアプリケーションを実行しようとしています。
私のマシンのDemoフォルダの中からdotnet runコマンドを実行すると正常に動作します。しかし、docker run -d --name demo Demoを使用して実行すると、コンテナはただちに終了します。.netコアコンソールアプリケーションでConsole.ReadLine()を使用しても、ドッキングコンテナがすぐに終了します

私は、ログをチェックするdocker logs demoを試してみましたが、それだけでConsole.WriteLineをからテキストを示しています...

と他には何を実行している

デモアプリ。

私はhttps://github.com/learningdockerandnetcore/Demo

プロジェクトがデモ画像を作成するために使用さ Programs.csDockerfileが含ま

、およびproject.jsonファイルでプロジェクトをアップロードしています。

+0

私は自分自身を学ぶためにしようとしている:私はあなたが対話モードでそれを実行すると、おそらく用語を追加したいと思います。 'docker run -it --name demo Demo' – hdz

+0

バックグラウンドモード(-d)で実行した場合、' docker attach {container} 'を使ってそれに戻ることもできます。すでに出力されているので出力は表示されませんが、コンテナを終了するにはenterキーを押すことができます – hdz

答えて

6

コンテナをインタラクティブモード(-iオプション付き)で実行する必要があります。ただし、コンテナを実行するときにバックグラウンドプロセスがすぐに終了するので、スクリプトがフォアグラウンドで実行されているか、単に機能しないことを確認してください。

+0

'-i'ではありません対話モード - デーモン(またはデタッチ)モードではありませんか? – Jay

+0

はい、 '-d'はデアモン/デタッチモードです。 – Peter

8

Docker/Linuxに.NET Coreアプリケーションを生き残らせる唯一の方法は、ASP.NETを私のためにホスティングすることです。これは醜いハックです!

このようにすると、docker run -dオプションを使用してDockerで実行されるため、STDINストリームを有効にするためにライブ接続する必要はありません。

私は.NETのコアコンソールアプリケーション(ない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を使用しています。

0

1より「汚いやり方は」

screen -dmS yourprogramm 
0

を使用して画面でプログラムを起動することです私は切り離さドッキングウィンドウコンテナ内DOTNETコアコンソールアプリケーションを実行するときConsole.ReadLine();は、メインスレッドをブロックしない理由はわかりませんしかし、最も良い解決策はConsoleCancelEventHandlerConsole.CancelKeyPressイベントで登録することです。

代わりに、スレッディングWaitHandleのタイプでメインスレッドをブロックし、Console.CancelKeyPressが起動されたときにメインスレッドのリリースを知らせることができます。

良い例のコードはここで見つけることができます:https://gist.github.com/kuznero/73acdadd8328383ea7d5を使用でき

0

代わりに動作するようです:

Thread.Sleep(Timeout.Infinite);

この回答はを参照してください。 。

C#:

do 
{ 
    Console.WriteLine($"Type: quit<Enter> to end {Process.GetCurrentProcess().ProcessName}"); 
} 
while (!Console.ReadLine().Trim().Equals("quit",StringComparison.OrdinalIgnoreCase)); 

F#:

while not (Console.ReadLine().Trim().Equals("quit",StringComparison.OrdinalIgnoreCase)) do 
    printfn "Type: quit<Enter> to end" 
関連する問題