这种情况是,我有一个用户空间文件系统,该系统可以在用户空间中提供一堆类似posix的界面。像这样:
open
read
write
mkdir
...
我想在此文件系统上创建一个卷并将其传递给docker。我的问题是我如何控制docker访问此卷的方式,以便可以将其重定向到类似posix的界面?现在,我的文件系统无法安装在主机上。它是一个完全用户空间的文件系统。我认为保险丝可以支持这一点,但是除非我别无选择,否则我不想去那里。
您在这里不需要音量。如果可以从在docker中运行的应用程序访问POSIX接口。您访问它并执行读,写等操作。如果确实需要卷实施,则需要将其存储到另一个卷中,并让看门狗应用将更改同步到您的用户文件系统。
Docker不实现任何文件或目录访问。就设计而言,这根本不是docker的工作。
启动容器时,所有docker所做的就是创建一堆安装,以使容器内的进程可以发出其常规POSIX调用。当容器内的某个进程调用write()
时,该调用将直接转到Linux内核,而无需docker的知识或干预。
现在,您的难题中有一个缺失的环节必须以一种或另一种方式实现:应用程序调用例如POSIX write()
函数,并且您的文件系统无法拦截此write()
函数。
所以您有两个选择:
选项1:在库中实现用户空间文件系统:
write()
函数。/build/artifacts/filesystem.so
。docker run -v /build/artifacts/filesystem.so:/extralibs/filesystem.so ...
docker run ... --env LD_LIBRARY_PATH=/extralibs ...
这将使容器中的所有调用使用您的库,因此它应将所有不相关的文件(例如/bin/bash
,/etc/passwd
等)转发到真实文件系统。
如果您可以控制图像,则可以对其进行设置,以使只有特定的命令才能用此LD_LIBRARY_PATH
执行。
公平警告:实现一个覆盖系统调用的库,而libc有很多陷阱,您需要解决。一个例子是如果程序使用例如fprintf()
,那么即使fprintf()
调用fprintf()
,您也必须覆盖write()
。
选项2:修改应用程序以仅调用您的filsystem函数。
这是假设您可以修改应用程序和docker映像。
如果文件系统是服务,请在容器中运行它并发出适当的RPC。
如果需要与其他容器共享,则文件系统的后备存储可以是卷。
选项3:使用户空间文件系统在容器中本机可用。
意味着任何命令都可以发出直接进入内核的write()
,并且内核会将其重定向到您的文件系统。
这本质上意味着将文件系统实现为保险丝守护程序,将其安装在主机上(了解如何无法将其安装在容器中,并将其用作docker卷。
如果存在特定限制,不允许您在主机上挂载文件系统,那么您需要做很多工作才能使选项1正常工作。否则,我建议您使用保险丝实现文件系统并将其安装在主机上-它具有最高的ROI。