Docker

NFS 共享上的 Docker 卷 - 空目錄

  • July 1, 2020

我們的業務應用程序在兩個節點(node1 和 node2)上執行了一個 Docker Swarm 部署。

應用程序需要一個卷來儲存持久數據。由於不清楚容器的部署位置(節點 1 或節點 2)以及我們應用程序的兩個容器應該在兩個節點上執行,我們需要一個解決方案來為所有節點提供共享卷。

為了共享卷,我們使用以下 /etc/exports 文件在第三個節點 3 上設置 NFS 伺服器:

/srv          *(rw,sync,anonuid=1000,anongid=1000,all_squash,subtree_check,crossmnt,fsid=root)

(我使用 anonuid/gid 為導出中的每個文件顯式設置 node3 系統中已知使用者的使用者資訊。all_squash 用於確保所有訪問使用者的所有文件權限都重寫給該本地使用者)

在我們的 docker-compose.yml 中,我們使用以下設置來包含卷:

volumes:
 nfs-data:
   driver: local
   driver_opts:
     type: nfs
     o: nfsvers=4,addr=node3.example.com,rw,nolock,soft

我們現在遇到了容器不想啟動的問題,錯誤消息是:

failed to copy file info for /var/lib/docker/volumes/MY_CONTAINER_nfs-data/_data: failed to chown /var/lib/docker/volumes/MY_CONTAINER_nfs-data/_data: lchown /var/lib/docker/volumes/MY_CONTAINER_nfs-data/_data: operation not permitted

經過一番探勘,我發現問題出在 node3 伺服器上導出的 NFS 目錄上的初始空文件夾中。一旦我放入一個空文件,node1 和 node2 中的容器的啟動就完全正常了。

有人對此有解釋嗎?

當命名卷從空/新狀態初始化時,docker 會將鏡像目錄的內容複製到命名卷中。有幾種選擇可以解決這個問題:

  1. 在容器啟動之前使用內容初始化命名卷。如您所見,這會禁用卷初始化步驟。
  2. 更新圖像以在目錄中具有所需的 uid/gid 並包含帶有RUN chown -R 1000:1000 /path. 這應該可以防止出現問題,但您需要進行測試以確保沒有 chown 試圖從 docker 執行,具體取決於它如何初始化這些文件。
  3. 在 NFS 上禁用 squash。這是 docker 卷問題的常見原因,我不確定您會獲得什麼安全優勢。如果您確實需要避免使用 root,您可以嘗試使用使用者命名空間配置 docker,但這會破壞您假設 uid 匹配的主機捲,因此請準備好一些努力。
  4. 禁用卷初始化。使用目前的 compose spec,您可以使用長語法將“nocopy”選項添加到您的服務量規範中。這是在使用卷的服務上完成的,而不是在定義卷的頂層。

docker 文件中關於“nocopy”選項的範例如下所示:

version: "3.8"
services:
 web:
   image: nginx:alpine
   ports:
     - "80:80"
   volumes:
     - type: volume
       source: mydata
       target: /data
       volume:
         nocopy: true

volumes:
 mydata:

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