Amazon-Web-Services

ECS 中的 Docker 卷權限

  • April 26, 2020

我正在將現有應用程序從在裸 EC2 實例上執行的遷移到使用 ECS 的容器化設置。我有兩種情況需要在容器之間共享數據。一個是儲存一些靜態和媒體文件的 EFS 共享,另一個是日誌目錄,以便我可以使用 Sidecar 容器中的 Cloudwatch Logs 代理將日誌推送到 Cloudwatch。

網路伺服器需要能夠將數據寫入這兩個位置,但到目前為止我還無法實現。日誌目錄是一個本地捲,歸root:root. 我按照這些說明設置的 EFS 共享歸1000:xfs(無使用者名)所有。在這兩種情況下,我的網路使用者 ( www-data) 都不能寫入這些位置。

如何告訴 ECS 在具有給定所有者和/或組的容器內掛載卷?

編輯:原來這比我做的要簡單得多。

當您在 ECS 上創建卷時,它會要求您輸入卷的名稱和“源路徑”。當按下解釋時,它將指定源路徑是“主機容器實例上的路徑,該路徑呈現給該卷的容器。如果省略,則 Docker 守護程序為您分配主機路徑。”

一切都很好,但事實證明,區別不僅僅是“指定目錄”與“Docker 為您選擇目錄”。這是docker 捲綁定掛載之間的區別,事實上,如果您docker inspect是容器,您將看到為 ECS 提供“源路徑”的捲 get "Type": "bind",而未指定的捲 get "Type": "volume"

綁定掛載和卷之間的一個關鍵區別是,雖然綁定掛載從主機文件系統繼承其所有權,但卷從容器文件系統繼承其所有權。因此,解決我的問題的令人難以置信的、令人沮喪的簡單解決方案就是確保該目錄存在於具有正確所有權的映像中,然後在 ECS 中創建捲而不指定源路徑。

順便說一句,如果您的應用程序涉及共享同一卷的多個容器,則該卷將從首先啟動並執行的任何容器上的現有目錄結構中獲取其權限。因此,您需要確保 a) 該目錄存在於將要掛載該卷的所有容器上,或者 b) 始終首先啟動具有該目錄的容器。

我將把我原來的解決方案留在下面,以防它對任何人有用。

原始解決方案 1:tmpfs 掛載

Docker 卷接受一個與 Linux 系統上driver_opts的命令類似的參數。mount因此,一種選擇是使用tmpfs掛載,它允許設置結果文件的所有者和組的選項。在 ECS 上,可以這樣實現:

{
 "name": "myvolume",
 "dockerVolumeConfiguration": {
   "scope": "task",
   "driver": "local",
   "driverOpts": {
     "type": "tmpfs",
     "device": "tmpfs",
     "o": "uid=1000,gid=1000"
   }
 }
}

這將在容器內創建一個由使用者和組 1000 擁有的捲。

這種方法的缺點是tmpfs,它將文件儲存在主機記憶體中。根據您的案例,這可能會或可能不會接受 - 對我來說這並不理想,因為我需要儲存可能會變得非常大的日誌文件。

(注意這裡的typeanddevice參數driverOpts等價於Linux命令type的anddevice參數。這花了我相當長的時間和挫折才弄明白。)mount

原始解決方案2:通過NFS匹配UID

NFS 只是將文件的所有者/組儲存為數字 id。該小組出現在xfs我身上的原因是,作為我重新部署的一部分,我正在從 Ubuntu 遷移到 Alpine。在這兩種情況下,我都想使用www-data該組,但www-data在 Ubuntu 上是使用者/組 33,在 Alpine 上是 82。在 Alpine 上,33 已經作為“X 字型伺服器”使用者存在,因此,xfs.

對於非持久性、共享的“臨時工作”目錄,我仍然沒有完美的解決方案,我可以在其中轉儲日誌,同時等待將它們發送到 Cloudwatch。我最終可能會簡單地使用 tmpfs 解決方案,然後使用一組非常激進的參數執行 logrotate,這樣日誌文件就不會消耗超過幾 MB 的記憶體。

引用自:https://serverfault.com/questions/991032