问题
The situation is that I have a user space file system which can provide a bunch of posix like interface in user space. Like this:
open
read
write
mkdir
...
I want to make a volume on this file system and pass it to a docker. My question is how can I control the way docker access this volume so that it can be redirected to my posix like interface? Right now my file system can't be mounted on the host. It is a completely user space file system. I think fuse can support this, but I don't want to go there unless I have no choice.
回答1:
You dont need a volume here. If you can access your POSIX interfaces from your application running in docker. You access it and perform read, write etc operations.
If you really need a volume implementation, you need to store it into another volume and have a watch dog app sync the changes to your user file system
回答2:
Docker does not implement any file or directory access. It's simply not what docker does, as a matter of design.
All docker does when launching a container is to create a bunch of mounts in such a way that the processes inside the container can issue their regular POSIX calls. When a process inside a container calls write()
, the call goes directly to the Linux kernel, without docker's knowledge or intervention.
Now, there's a missing piece in your puzzle that has to be implemented one way or another: The application calls e.g. POSIX write()
function, and your filesystem is not able to intercept this write()
function.
So you have a couple of options:
Option 1: Implement your userspace filesystem in a library:
- The library would override the
write()
function. - You compile the library and put it in some directory e.g.
/build/artifacts/filesystem.so
. - You use that directory as a volume when running the container, e.g.
docker run -v /build/artifacts/filesystem.so:/extralibs/filesystem.so ...
- you add this filesystem as a preloaded library:
docker run ... --env LD_LIBRARY_PATH=/extralibs ...
This will make all calls in the container use your library, so it should forward all the irrelevant files (e.g. /bin/bash
, /etc/passwd
etc.) to the real filesystem.
If you have control over the images, then you can set it up such that only particular commands execute with this LD_LIBRARY_PATH
.
Fair warning: implementing a library which overrides system calls and libc has a lot of pitfalls that you'll need to work around. One example is that if the program uses e.g. fprintf()
, then you have to override fprintf()
as well, even though fprintf()
calls write()
.
Option 2: Modify the application to just call your filsystem functions.
This is assuming you can modify the application and the docker image.
If your filesystem is a service, run it in the container and issue the appropriate RPCs.
If it needs to be shared with other containers, then the backing store for your filesystem can be a volume.
Option 3: Make your userspace filesystem available natively within the container.
Meaning any command can issue a write()
that goes to the kernel directly, and the kernel redirects it to your filesystem.
This essentially means implementing your filesystem as a fuse daemon, mounting it on the host (seeing how you can't mount it inside containers), and using it as a docker volume.
If there's a specific limitation that you're not allowed to mount your filesystem on the host, then you have a lot of work to do to make option 1 work. Otherwise I would advise you to implement your filesystem with fuse and mount it on the host - it has the highest ROI.
来源:https://stackoverflow.com/questions/59026367/how-to-control-file-operations-made-to-a-volume-in-docker