如何控制docker中对卷的文件操作?

如何控制docker中对卷的文件操作?,docker,filesystems,storage,driver,volume,Docker,Filesystems,Storage,Driver,Volume,情况是,我有一个用户空间文件系统,它可以在用户空间中提供一系列类似posix的接口。像这样: open read write mkdir ... 我想在此文件系统上创建一个卷并将其传递给docker。我的问题是,如何控制docker访问此卷的方式,以便将其重定向到类似于posix的接口? 现在我的文件系统无法安装在主机上。它是一个完全的用户空间文件系统。 我认为fuse可以支持这一点,但除非我别无选择,否则我不想去那里。这里不需要卷。如果可以从docker中运行的应用程序访问POSIX接口

情况是,我有一个用户空间文件系统,它可以在用户空间中提供一系列类似posix的接口。像这样:

open
read 
write 
mkdir
...
我想在此文件系统上创建一个卷并将其传递给docker。我的问题是,如何控制docker访问此卷的方式,以便将其重定向到类似于posix的接口? 现在我的文件系统无法安装在主机上。它是一个完全的用户空间文件系统。
我认为fuse可以支持这一点,但除非我别无选择,否则我不想去那里。

这里不需要卷。如果可以从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_PRELOAD=/extralibs/filesystem.so…
  • 这将使容器中的所有调用都使用您的库,因此它应该将所有不相关的文件(例如
    /bin/bash
    /etc/passwd
    等)转发到真正的文件系统

    如果您对图像有控制权,则可以将其设置为仅使用此
    LD_PRELOAD
    执行特定命令

    公平警告:实现一个覆盖系统调用和libc的库有很多缺陷,需要解决。一个例子是,如果程序使用例如
    fprintf()
    ,那么您也必须重写
    fprintf()
    ,即使
    fprintf()
    调用
    write()

    选项2:修改应用程序以仅调用系统功能

    这是假设您可以修改应用程序和docker映像

    如果您的文件系统是一个服务,请在容器中运行它并发出相应的RPC

    如果需要与其他容器共享,那么文件系统的备份存储可以是一个卷

    选项3:使您的用户空间文件系统在容器中本机可用

    这意味着任何命令都可以发出一个直接进入内核的
    write()
    ,内核会将它重定向到您的文件系统

    这本质上意味着将文件系统实现为一个fuse守护进程,将其安装在主机上(查看如何无法将其安装在容器中),并将其用作docker卷


    如果存在不允许在主机上装载文件系统的特定限制,那么要使选项1起作用,您需要做很多工作。否则,我建议您使用fuse实现文件系统并将其装载到主机上-它具有最高的ROI。

    感谢您的回答,也许我不清楚,docker中的应用程序只能在给定路径上运行,在docker中更改所有应用程序可能既不可行也不经济。我选择docker的原因是为了支持尽可能多的应用程序,我想如果我可以控制docker操作卷的方式并重定向到我的界面,这可能会更容易。我明白你的意思。但总有一些解决方案是可以构建的。我的想法是实现一个对所有应用程序容器都通用的容器。此容器是一个双向实现,它接受来自所有应用程序的卷请求,并将它们转换为POSIX调用,获取返回并返回到应用程序容器。谢谢,另一个容器。。。嗯,我想我可以接受,但我的问题仍然是,我不知道如何控制docker访问卷的方式,说得清楚,我不知道如何控制docker访问该docker中的卷的方式或从该docker外部(即主机端)访问卷的方式,docker如何使用容器处理卷。当然,一本书应该对你有所帮助。您需要读取卷、Bindmounts和tmpfs装载。行动中的码头工人必须帮忙。提示一下,当你映射一个卷时,docker将这些文件存储在它的卷存储中,当你使用bind mount时,你可以将你的任何目录作为卷数据绑定到你的容器中。我尝试了卷驱动程序,但最终我相信卷驱动程序只能控制docker处理卷本身的方式,但不是docker处理其中的文件或目录,你是否暗示我可以通过更改docker本身并重新编译它来实现这一点?准确地说,如果可执行文件与C库静态链接,它将无法工作。