Docker
NFS 共享上的 Docker 卷 - 空目錄
我們的業務應用程序在兩個節點(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 會將鏡像目錄的內容複製到命名卷中。有幾種選擇可以解決這個問題:
- 在容器啟動之前使用內容初始化命名卷。如您所見,這會禁用卷初始化步驟。
- 更新圖像以在目錄中具有所需的 uid/gid 並包含帶有
RUN chown -R 1000:1000 /path
. 這應該可以防止出現問題,但您需要進行測試以確保沒有 chown 試圖從 docker 執行,具體取決於它如何初始化這些文件。- 在 NFS 上禁用 squash。這是 docker 卷問題的常見原因,我不確定您會獲得什麼安全優勢。如果您確實需要避免使用 root,您可以嘗試使用使用者命名空間配置 docker,但這會破壞您假設 uid 匹配的主機捲,因此請準備好一些努力。
- 禁用卷初始化。使用目前的 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: