簡體   English   中英

Docker 設計:在容器之間交換數據還是將多個進程放在一個容器中?

[英]Docker design: exchange data between containers or put multiple processes in one container?

在當前項目中,我必須執行以下任務(除其他外):

  • 從五個 IP 攝像機捕獲視頻幀並拼接全景圖
  • 在全景圖上運行基於機器學習的對象檢測
  • 流式傳輸全景圖,以便它可以顯示在 UI 中

目前,拼接和流式傳輸在一個 docker 容器中運行,對象檢測在另一個容器中運行,讀取全景流作為輸入。

由於我需要在保持 UI 的流分辨率的同時增加對象檢測器的輸入分辨率,因此我必須尋找其他方法來從拼接器容器獲取拼接(全分辨率)全景(每幀約 10 MB)到探測器容器。

我對潛在解決方案的看法:

  • 共享卷。 潛在的缺點:每幀額外的一次寫入和讀取可能太慢了?
  • 使用消息隊列或例如 redis。 潛在的缺點:架構中的另一個組件。
  • 合並兩個容器。 潛在的缺點:不僅感覺不對,而且兩個容器具有完全不同的基礎鏡像和依賴項。 另外,我不得不擔心並行化。

由於我不是 docker 抽屜里最鋒利的刀,我所要求的是有關 docker 容器之間快速數據交換的技巧、經驗和最佳實踐。

通常 Docker 容器之間的大多數通信是通過網絡套接字進行的。 當您與諸如關系數據庫或 HTTP 服務器之類的東西交談時,這很好。 不過,聽起來您的應用程序更多的是關於共享文件,而 Docker 不太擅長這一點。

如果您只想要每個組件的一個副本,或者仍在積極開發管道:我可能不會為此使用 Docker。 由於每個容器都有一個獨立的文件系統和自己的用戶 ID 空間,因此共享文件可能會出乎意料地棘手(每個容器必須就數字用戶 ID 達成一致)。 但是如果你只是在主機上運行所有東西,作為同一個用戶,指向同一個目錄,這不是問題。

如果你想在生產中擴展它:我會添加某種共享文件系統和一個消息隊列系統,比如 RabbitMQ。 對於本地工作,這可能是一個 Docker 命名的卷或綁定安裝的主機目錄; 像 Amazon S3 這樣的雲存儲也可以正常工作。 設置是這樣的:

  • 每個組件都知道共享存儲並連接到 RabbitMQ,但不知道其他組件。
  • 每個組件從 RabbitMQ 隊列中讀取一條消息,該隊列命名一個要處理的文件。
  • 該組件讀取文件並完成其工作。
  • 完成后,組件將結果文件寫回共享存儲,並將其位置寫入 RabbitMQ 交換。

在這個設置中,每個組件都是完全無狀態的。 例如,如果您發現它的機器學習組件最慢,您可以運行它的重復副本。 如果出現問題,RabbitMQ 會記住給定的消息還沒有被完全處理(確認); 再次由於隔離,您可以在本地運行該特定組件以重現和修復問題。

該模型還可以很好地轉換為更大規模的基於 Docker 的集群計算系統,如 Kubernetes。

在本地運行它,我絕對會在單獨的容器中保留單獨的關注點(特別是如果單獨的圖像處理和 ML 任務很昂貴)。 我建議的設置需要一個消息隊列(以跟蹤工作)和一個共享文件系統(因為消息隊列往往不會針對 10 MB 以上的單個消息進行優化)。 您可以在 Docker 命名卷和主機綁定掛載之間進行選擇,作為現成的共享存儲。 綁定掛載更容易檢查和管理,但在某些平台上速度非常慢。 我認為命名卷相當快,但您只能從 Docker 容器訪問它們,這意味着需要啟動更多容器來執行備份和修剪等基本操作。

好吧,讓我們解開這個:

  • 恕我直言,共享卷工作得很好,但隨着時間的推移變得過於混亂。 特別是如果您正在處理有狀態服務。
  • MQ:在我看來,這似乎是最好的選擇。 是的,它是您架構中的另一個組件,但擁有它而不是維護凌亂的共享卷或處理大量容器映像(如果您設法組合 2 個容器映像)是有意義的
  • 是的,您可能會這樣做,但不是一個好主意。 考慮到您的用例,我將繼續假設您有大量可能導致沖突的依賴項。 此外,大量依賴 = 更大的圖像 = 更大的攻擊面 - 從安全角度來看,這不是一件好事。

如果你真的想在一個容器中運行多個進程,這是可能的。 有多種方法可以實現這一點,但我更喜歡supervisord

https://docs.docker.com/config/containers/multi-service_container/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM