使主機上的 NFS 掛載在 Docker 容器內可見並可讀寫

使主機上的 NFS 掛載在 Docker 容器內可見並可讀寫

我是 Docker 新手,我想使用它為我的程式碼獲得受控的編譯環境。

我已經擁有一個包含我需要的所有工具的 Docker 映像。我目前的問題如下:

  • 我的程式碼位於主機中,位於從 NFS 伺服器掛載的主資料夾中
  • 我想讓這個資料夾在 Docker 容器內可見並具有 r+w 權限

這是我首先嘗試的方法(將來源資料夾作為磁碟區運行容器)以及收到的錯誤:

[mbrandalero@machine ~]$ docker run -it --cap-add sys_admin -v "/homes/mbrandalero/src:/usr/local/src/" mbrandalero/my-image bash
/usr/bin/docker-current: Error response from daemon: error while creating mount source path '/homes/mbrandalero/src': mkdir /homes/mbrandalero/src: permission denied.

(顯然它正在嘗試在主機端創建目錄,但它已經在那裡)

奇怪的是,當我嘗試將整個主資料夾作為磁碟區運行容器時,它可以工作,但會產生不同的錯誤(資料夾中沒有寫入權限):

[mbrandalero@machine ~]$ docker run -it --cap-add sys_admin -v "/homes/mbrandalero/:/usr/local/src/home" mbrandalero/my_image bash
root@46712ad936f2:/usr/local/src# cd home/
bash: cd: home/: Permission denied
root@46712ad936f2:/usr/local/src# ls -lah | grep "\(\.\|home\)"
total 4.0K
drwxr-xr-x  1 root  root    18 May 20 14:50 .
drwxr-xr-x  1 root  root    17 May 15 14:06 ..
drwxr-x--- 30 10031 10031 4.0K May 20 15:03 home

我做對了嗎?我缺什麼?

附加資訊:

  • 作業系統:CentOS Linux 7.6
  • 泊塢窗版本:1.13.1

更新(1):

顯然,在運行時設定使用者 IDdocker run可以解決問題,但這是正確的方法嗎?以這種方式運行它可以解決一些問題,但看起來很奇怪(我得到“我沒有名字!”作為用戶名):

[mbrandalero@machine ~]$ docker run -it --cap-add sys_admin -v "/homes/mbrandalero/:/usr/local/src/home" --user $(id -u) mbrandalero/my_image bash
I have no name!@2efec822e572:/usr/local/src$ cd home/
I have no name!@2efec822e572:/usr/local/src/home$

答案1

正如您在更新中所指出的,檔案上的 UID 未對應到綁定掛載中,這就是 Linux 進行綁定掛載的方式。您可以使用不同的 UID 啟動容器,但這將導致容器內的 /etc/passwd 映射到不同的用戶,甚至沒有(在您的情況下)用戶。有多種選項,但我更喜歡使用 usermod 命令修改容器的 UID,該命令在映像的入口點內運行修復權限腳本。這需要以 root 身份運行,但您可以gosu在運行命令時使用回退到使用者。我在我的dockercon 演示


請注意,您也可以直接在 NFS 伺服器上執行磁碟區掛載,而不是綁定掛載到主機 NFS 目錄。以下是如何執行此操作的幾個範例:

  # create a reusable volume
  $ docker volume create --driver local \
      --opt type=nfs \
      --opt o=nfsvers=4,addr=nfs.example.com,rw \
      --opt device=:/path/to/dir \
      foo

  # or from the docker run command
  $ docker run -it --rm \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=nfs.example.com\",volume-opt=device=:/host/path \
    foo

  # or to create a service
  $ docker service create \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=nfs.example.com\",volume-opt=device=:/host/path \
    foo

  # inside a docker-compose file
  ...
  volumes:
    nfs-data:
      driver: local
      driver_opts:
        type: nfs
        o: nfsvers=4,addr=nfs.example.com,rw
        device: ":/path/to/dir"
  ...

答案2

如果您以 身分執行容器root,您可能會遇到該error while creating mount source path ... permission denied訊息,因為 NFS 主機正在重新對應所有遠端根 UID(又稱 root-squash)。

https://en.wikipedia.org/wiki/Unix_security#Root_squash

這是一項面向安全的功能,可防止不良行為者以自己的root使用者身分安裝您的共享,然後對資料做壞事。因此,NFS 掛載通常會root_squash預設設定選項,以防止此類問題。如果您需要容器作為 運行root,您可以使用no_root_squashNFS 主機/etc/exports檔案中的選項覆蓋此設定。

/srv/nfs/shared_folder <hostname>(rw,sync,no_subtree_check,no_root_squash)

http://nfs.sourceforge.net/nfs-howto/ar01s03.html

https://www.thegeekdiary.com/understanding-the-etc-exports-file/

答案3

這對我有用 - 將主機 nfs 路徑聲明為容器的磁碟區。且主機nfs路徑是非主目錄路徑,它不是主目錄。

我的主機 nfs 掛載點:/mnt/abc

我的 docker-compose.yml 檔案片段。

   ...
   volumes:
  - /mnt/abc/:/abc
   ...

相關內容