2016-07-24 17 views
7

Tôi đang cố gắng chạy ứng dụng bảng điều khiển lõi .net lõi bên trong một vùng chứa docker.
Khi tôi chạy dotnet run lệnh từ bên trong thư mục Demo trên máy của tôi, nó hoạt động tốt; Nhưng khi chạy bằng cách sử dụng docker run -d --name demo Demo, vùng chứa sẽ thoát ngay lập tức.thoát khỏi vùng chứa dock ngay lập tức ngay cả với Console.ReadLine() trong ứng dụng bảng điều khiển lõi .net

tôi đã cố gắng docker logs demo để kiểm tra các bản ghi và nó chỉ hiển thị nội dung các Console.WriteLine:

Demo ứng dụng đang chạy ...

và không có gì khác.

Tôi đã tải lên dự án tại https://github.com/learningdockerandnetcore/Demo

Dự án chứa Programs.cs, Dockerfile sử dụng để tạo Demo hình ảnh, và project.json tập tin.

+0

Tôi đang cố gắng tìm hiểu bản thân mình: Tôi nghĩ rằng bạn muốn chạy nó trong chế độ tương tác và có thể muốn thêm một nhiệm kỳ. 'docker run -it --name demo Demo' – hdz

+0

bạn cũng có thể đính kèm vào nó' docker attach {container} 'để quay lại nó nếu bạn chạy nó ở chế độ nền (-d). Bạn sẽ không nhìn thấy đầu ra vì nó đã xuất ra nhưng bạn sẽ có thể nhấn enter cho vùng chứa để thoát khỏi – hdz

Trả lời

6

Bạn nên chạy vùng chứa của mình ở chế độ Tương tác (với tùy chọn -i). nhưng xin lưu ý rằng các quy trình nền sẽ bị đóng ngay lập tức khi bạn chạy vùng chứa để đảm bảo tập lệnh của bạn được chạy ở nền trước hoặc đơn giản là nó sẽ không hoạt động.

+0

Không phải là '-i' Chế độ tương tác - không phải chế độ daemon (hoặc tách ra)? – Jay

+0

Có, '-d' là chế độ deamon/tách rời. – Peter

8

Cách duy nhất tôi có thể lấy Docker/Linux để giữ ứng dụng .NET Core của tôi còn sống là giả mạo ASP.NET vào lưu trữ nó cho tôi ... Đây là một hack xấu xí như vậy !!

Làm theo cách này sẽ chạy trong Docker bằng cách sử dụng tùy chọn docker run -d, do đó bạn không cần phải có kết nối trực tiếp để giữ luồng STDIN còn sống.

tôi tạo một giao diện điều khiển ứng dụng .NET Core (không phải là một ứng dụng ASP.NET) và lớp Chương trình của tôi trông như thế này:

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(); 
     } 
    }  
} 

Các Startup lớp:

public class Startup 
{ 
    public void ConfigureServices(IServiceCollection services) 
    { 
     services.AddSingleton<IServer, ConsoleAppRunner>(); 
    } 


    public void Configure(IApplicationBuilder app, IHostingEnvironment env) 
    { 
    } 
} 

Lớp 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. 

    } 
} 

Điều tuyệt vời duy nhất là bạn có thể sử dụng DI trong ứng dụng của mình (nếu bạn muốn) - vì vậy trong trường hợp sử dụng của tôi, tôi đang sử dụng ILoggingFactory để xử lý việc ghi nhật ký của mình.

0

thêm một "đường bẩn" là để bắt đầu chương trình của bạn trong màn hình sử dụng

screen -dmS yourprogramm 
0

Tôi không chắc chắn lý do tại sao Console.ReadLine(); không chặn các chủ đề chính khi chạy một giao diện điều khiển ứng dụng DotNet cốt lõi trong một container Docker tách , nhưng giải pháp tốt nhất là đăng ký ConsoleCancelEventHandler với sự kiện Console.CancelKeyPress.

Sau đó, bạn có thể chặn luồng chính bằng loại Luồng WaitHandle và báo hiệu việc giải phóng sợi chính khi Console.CancelKeyPress bị kích hoạt.

Một ví dụ mã tốt có thể được tìm thấy ở đây: https://gist.github.com/kuznero/73acdadd8328383ea7d5

0

Sử dụng Console.ReadLine thay vì dường như làm việc .

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" 
Các vấn đề liên quan