【茶包射手日記】.NET Core File Watcher 在 Docker 環境下失效

栏目: ASP.NET · 发布时间: 5年前

内容简介:遇到一個問題,.NET Core 的 File Watcher 機制(在檔案新增修改刪除時觸發 .NET 事件,註:File Watcher 可做到 Config 檔修改讀取生效、程式檔案異動時重新編譯,或是資料檔改變清除 Cache,非常實用。以下是我重現問題的範例:

遇到一個問題,.NET Core 的 File Watcher 機制(在檔案新增修改刪除時觸發 .NET 事件, 參考 )在 Docker 中可能失效。

註:File Watcher 可做到 Config 檔修改讀取生效、程式檔案異動時重新編譯,或是資料檔改變清除 Cache,非常實用。

以下是我重現問題的範例:

class Program
{
    private static PhysicalFileProvider _fileProvider =
new PhysicalFileProvider(Directory.GetCurrentDirectory());
    static void Main(string[] args)
    {
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(5000);
            Console.WriteLine("update quotes after 5 seconds");
            File.WriteAllText("quotes.txt", DateTime.Now.ToString());
        });
        WaitFileChange().GetAwaiter().GetResult();
        Console.WriteLine("done");
    }

    static async Task WaitFileChange()
    {
        IChangeToken token = _fileProvider.Watch("quotes.txt");
        var tcs = new TaskCompletionSource<object>();
        token.RegisterChangeCallback(state =>
        ((TaskCompletionSource<object>)state).TrySetResult(null), tcs);
        await tcs.Task.ConfigureAwait(false);
        Console.WriteLine("quotes.txt changed");
    }
}

程式的運作原理為使用 PhysicalFileProvider.Watch() 觀注 quotes.txt 檔案,以 IChangeToken.RegisterChangeCallback() 註冊檔案變更事件並利用 TaskCompletionSource 同步化,在檔案變更時印出 "quotes.txt changed"。在此同時,另開一條 Thread 在 5 秒後複寫 quotes.txt 檔案以觸發事件,故正常狀況應為,程式開始後等待五秒出現 "update quotes after 5 seconds",隨即印出 "quotes.txt changed",最後顯示 "done" 測試完成。

程式在 Windows 測試 OK,部署到 Linux 執行也沒問題,包進 Docker 裡跑結果也正確,但若使用 Docker Volume 將 /app/quotes.txt 對映到實體主機的 /home/jeffrey/dockers/fwt/quotes.txt 時,本機的 quotes.txt 檔案會被覆寫,但 RegisterChangeCallback() 事件不會被觸發。

【茶包射手日記】.NET Core File Watcher 在 Docker 環境下失效

.NET Core File Providers 文件 是有提到這點:

Some file systems, such as Docker containers and network shares, may not reliably send change notifications. Set the DOTNET_USE_POLLING_FILE_WATCHER environment variable to 1 or true to poll the file system for changes every four seconds (not configurable).

意思是這個機制遇到 Docker 檔案系統可能失效,必須設定 DOTNET_USE_POLLING_FILE_WATCHER 環境變數為 1 或 true,改用 4 秒一次的輪詢取代。實務上可在啟動 Docker 時透過 docker run ... -e DOTNET_USE_POLLING_FILE_WATCHER=1 ... 參數指定,更治本的解法則是在 Dockerfile 宣告 ENV 內嵌到容器裡:

FROM microsoft/dotnet:2.1-runtime
ENV DOTNET_USE_POLLING_FILE_WATCHER=1
WORKDIR /app
COPY ./publish ./
ENTRYPOINT ["dotnet", "FileWatcherTest.dll"]

貌似一行搞定,但我卻在這裡陷入泥坑,設好 DOTNET_USE_POLLING_FILE_WATCHER 卻不見無效,原以為可以輕鬆寫完的文章,反覆試了近兩多小時,將近午夜電腦都要變回南瓜仍然無解,讓我萬念俱灰了無生趣。

爬文時由一則 Github Issue 追到另一則被合併至 2.2 版的相關 PR ,浮現靈感,查詢我安裝 Microsoft.Extensions.FileProviders.Physical 的 NuGet 套件版本為 2.1 穩定版,改裝 2.2 Preview 姑且一試。

【茶包射手日記】.NET Core File Watcher 在 Docker 環境下失效

喵的,就這麼成功了~

【茶包射手日記】.NET Core File Watcher 在 Docker 環境下失效

這枚升級 2.2 預覽才解掉的茶包,算是我第一次踩到的 .NET Core + Docker 地雷,不怕不怕,呵。

補充今天查到的 Docker Image 版本補充 ,你知道 2.1-runtime-deps、2.1-runtime 有什麼不同? 什麼情況該用哪一種?

  • microsoft/dotnet:2.1.0-runtime-deps - use for deploying self-contained deployment apps
  • microsoft/dotnet:2.1.0-runtime - use for deploying .NET Core console apps
  • microsoft/dotnet:2.1.0-aspnetcore-runtime - use for deploying ASP.NET Core apps
  • microsoft/dotnet:2.1.300-sdk - use for building .NET Core (or ASP.NET Core apps)

Using an example to reproduce file watcher issue in Docker with volume mapping. Setting DOTNET_USE_POLLING_FILE_WATCHER=1 doesn't works with Microsoft.Extensions.FileProviders.Physical 2.1, upgrade to 2.2 preview is the workaround.


以上所述就是小编给大家介绍的《【茶包射手日記】.NET Core File Watcher 在 Docker 環境下失效》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

日赚500元

日赚500元

董俊峰 / 2008-5 / 20.00元

《日赚500元:揭开网络赚钱的秘密》是一本大学生网络创业必看的图书,一本想在网络上创业的人必看的图书。懂懂团队第一个操作Google FireFox下载项目,第一个操作“域名停靠”项目。第一个操作Google账号推介项目。首次提出“网赚”这个概念,并创造性地将“网赚”的过程分为3个阶段。《日赚500元:揭开网络赚钱的秘密》揭开了网络上一些行为的本质。一起来看看 《日赚500元》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具