在 docker 容器内挂载 nfs 共享
Posted
技术标签:
【中文标题】在 docker 容器内挂载 nfs 共享【英文标题】:Mounting nfs shares inside docker container 【发布时间】:2017-02-16 17:50:29 【问题描述】:有谁知道如何使用 centos 基础镜像?我试过这个命令:
mount server:/dir /mount/point
并得到下一个错误:
mount.nfs: rpc.statd is not running but is required for remote locking.
mount.nfs: Either use '-o nolock' to keep locks local, or start statd.
mount.nfs: an incorrect mount option was specified
当我尝试将它与 -o nolock 选项一起使用时,错误是:
mount.nfs: Operation not permitted
【问题讨论】:
您可以参考下面的链接。 ***.com/questions/45282608/… 【参考方案1】:从 docker 17.06 开始,您可以在运行时直接将 NFS 共享挂载到容器中,无需额外功能
export NFS_VOL_NAME=mynfs
export NFS_LOCAL_MNT=/mnt/mynfs
export NFS_SERVER=my.nfs.server.com
export NFS_SHARE=/my/server/path
export NFS_OPTS=vers=4,soft
docker run --mount \
"src=$NFS_VOL_NAME,dst=$NFS_LOCAL_MNT,volume-opt=device=:$NFS_SHARE,\"volume-opt=o=addr=$NFS_SERVER,$NFS_OPTS\",type=volume,volume-driver=local,volume-opt=type=nfs" \
busybox ls $NFS_LOCAL_MNT
或者,您可以在容器之前创建卷:
docker volume create \
--driver local \
--opt type=nfs \
--opt o=addr=$NFS_SERVER,$NFS_OPTS \
--opt device=:$NFS_SHARE \
$NFS_VOL_NAME
docker run --rm -v $NFS_VOL_NAME:$NFS_LOCAL_MNT busybox ls $NFS_LOCAL_MNT
得到了提示
https://github.com/moby/moby/issues/28809
来自 docker 的官方文档:https://docs.docker.com/storage/volumes/#create-a-service-which-creates-an-nfs-volume
【讨论】:
这应该是 Docker 17.06 及更高版本的第一答案。我为这个功能等待了很长时间! 我已经编辑了答案以修正一个错字并突出显示人们通常想要自定义的参数(容器中的本地安装点、NFS 服务器主机名/IP 和远程 NFS 共享路径) 我仍在尝试了解嵌入式安装选项,但看起来这个对我有用。我真的很喜欢它在为容器创建挂载的过程中幂等地创建卷。 你能用同样的方法来绑定挂载而不是卷吗? 完全按照你写的操作我得到no such file or directory
,尽管我可以使用完全相同的设置从我的主机手动挂载。【参考方案2】:
要使用mount
,您需要CAP_SYS_ADMIN
功能,该功能在创建容器时由 Docker 删除。
有几种解决方案:
-
使用
--cap-add sys_admin
标志启动容器。这会导致 Docker 保留 CAP_SYS_ADMIN
功能,这应该允许您从容器内挂载 NFS 共享。这可能是一个安全问题;不要在不受信任的容器中执行此操作。 [此答案的先前版本建议使用--privileged=true
来保留所有 功能,感谢@earcam 建议使用--cap-add
代替]。
在主机上挂载 NFS 共享并将其作为主机卷传递到容器中:
you@host > mount server:/dir /path/to/mount/point
you@host > docker run -v /path/to/mount/point:/path/to/mount/point
使用 Docker 卷插件(如 Netshare 插件)将 NFS 共享直接挂载为容器卷:
you@host > docker run \
--volume-driver=nfs \
-v server/dir:/path/to/mount/point \
centos
【讨论】:
对于选项1:不使用--privileged=true
时如何解决?
方法 2. 似乎不起作用。我在本地系统上安装了 NFS,我可以看到所有文件。但是,当我将挂载文件夹作为卷传递给容器时,我只会得到一个空文件夹。我尝试按照邱静的建议更改权限,但没有成功。
(2019 年)--cap-add
提供比--privileged=true
更细粒度的控制
@earcam 感谢您的建议!我已将其纳入我的答案中。
您好@helmbert,我对您的建议 2 有疑问,一些容器需要 chown 他们在挂载目录中创建的文件。但是,NFS 不允许根据我的发现进行此操作。您是否找到了解决方法,或者您没有遇到任何这样做的容器?【参考方案3】:
对于已接受答案中列出的第二个选项,我不确定您是否真的尝试使用 "docker run -v"
命令将主机上的 NFS 共享作为卷传递给 docker 容器。
我最近尝试这样做,以下是主机上 nfs 共享的信息:
nfs-server:/path_to_mount on /path_dest type nfs
然后:
docker run -it -v /path_dest:/path_in_docker docker_name bash
但是docker daemon总是报如下错误:
docker: Error response from daemon: stat /path_dest: permission denied.
经过多次搜索,我发现错误实际上来自docker daemon,它以“root”身份运行。当 docker 运行带有要挂载的卷的容器时,它会请求 docker daemon 来挂载它。问题是,NFS 服务器会以不同的方式处理 "root"。默认情况下,NFS 服务器会将 "root" 映射到 "nobody",导致错误信息:reference
【讨论】:
我也有同样的问题,你解决了吗? 我对“nobody”也有同样的问题。肮脏的解决方法是对 NFS 服务器使用“no_root_squash”。如果 IT 不允许您这样做,嗯...【参考方案4】:将--cap-add sys_admin
标志添加到客户端容器对我来说还不够。我收到错误:
mount.nfs: mount(2): Permission denied
mount.nfs: access denied by server while mounting 1.2.3.4:/exports
经过数小时的研究,我发现似乎需要完全权限 --privileged
才能在 docker 容器中正确挂载..
别忘了在你的 docker 容器中安装必要的 nfs 客户端包。在基于 debian 的容器上:
apt-get install -y nfs-common
【讨论】:
【参考方案5】:我将 nfs 安装在 docker 容器上,感谢 @helmbert。
使用 --privileged=true
标志运行 docker 容器。
$ docker run -it --privileged=true centos:7 bash
[root@f7915ae635aa /]# yum install -y nfs-utils
在CentOS上安装nfs工具包并挂载nfs。
[root@f7915ae635aa /]# yum install -y nfs-utils
[root@f7915ae635aa /]# mount -t nfs example.tw:/target/ /srv -o nolock
显示 nfs 服务器的挂载。
[root@f7915ae635aa /]# showmount example.tw
Hosts on example.tw:
10.10.10.1
10.10.10.2
【讨论】:
以上是关于在 docker 容器内挂载 nfs 共享的主要内容,如果未能解决你的问题,请参考以下文章
在不同 docker-compose 文件中描述并在不同 docker-machines 中运行的容器之间创建 NFS 共享