
我是 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_squash
NFS 主機/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
...